/// <summary> /// </summary> /// <param name="reader"> /// </param> /// <param name="head"> /// </param> /// <param name="bits"> /// </param> internal MsfDirectory(PdbReader reader, PdbFileHeader head, BitAccess bits) { bits.MinCapacity(head.directorySize); var pages = reader.PagesFromSize(head.directorySize); // 0..n in page of directory pages. reader.Seek(head.directoryRoot, 0); bits.FillBuffer(reader.reader, pages * 4); var stream = new DataStream(head.directorySize, bits, pages); bits.MinCapacity(head.directorySize); stream.Read(reader, bits); // 0..3 in directory pages int count; bits.ReadInt32(out count); // 4..n var sizes = new int[count]; bits.ReadInt32(sizes); // n..m this.streams = new DataStream[count]; for (var i = 0; i < count; i++) { if (sizes[i] <= 0) { this.streams[i] = new DataStream(); } else { this.streams[i] = new DataStream(sizes[i], bits, reader.PagesFromSize(sizes[i])); } } }
public static Module GetCodeModelFromMetadataModel(IMetadataHost host, IModule module, PdbReader/*?*/ pdbReader, DecompilerOptions options = DecompilerOptions.None) { Contract.Requires(host != null); Contract.Requires(module != null); Contract.Requires(!(module is Dummy)); Contract.Ensures(Contract.Result<Module>() != null); return GetCodeModelFromMetadataModelHelper(host, module, pdbReader, pdbReader, options); }
public static Assembly GetCodeModelFromMetadataModel(IMetadataHost host, IAssembly assembly, PdbReader/*?*/ pdbReader, DecompilerOptions options = DecompilerOptions.None) { Contract.Requires(host != null); Contract.Requires(assembly != null); Contract.Requires(!(assembly is Dummy)); Contract.Ensures(Contract.Result<Assembly>() != null); return (Assembly)GetCodeModelFromMetadataModelHelper(host, assembly, pdbReader, pdbReader, options); }
public VisualSourceEmitter(ISourceEmitterOutput sourceEmitterOutput, IMetadataHost host, PdbReader/*?*/ pdbReader, bool noIL, bool printCompilerGeneratedMembers) : base(sourceEmitterOutput) { this.host = host; this.pdbReader = pdbReader; this.noIL = noIL; this.printCompilerGeneratedMembers = printCompilerGeneratedMembers; }
/// <summary> /// </summary> /// <param name="read"> /// </param> /// <param name="bits"> /// </param> /// <param name="readAllStrings"> /// </param> /// <returns> /// </returns> /// <exception cref="PdbException"> /// </exception> internal static PdbFunction[] LoadFunctions(Stream read, BitAccess bits, bool readAllStrings) { var head = new PdbFileHeader(read, bits); var reader = new PdbReader(read, head.pageSize); var dir = new MsfDirectory(reader, head, bits); DbiModuleInfo[] modules = null; DbiDbgHdr header; dir.streams[1].Read(reader, bits); var nameIndex = LoadNameIndex(bits); int nameStream; if (!nameIndex.TryGetValue("/names", out nameStream)) { throw new PdbException("No `name' stream"); } dir.streams[nameStream].Read(reader, bits); var names = LoadNameStream(bits); dir.streams[3].Read(reader, bits); LoadDbiStream(bits, out modules, out header, readAllStrings); var funcList = new ArrayList(); if (modules != null) { for (var m = 0; m < modules.Length; m++) { if (modules[m].stream > 0) { dir.streams[modules[m].stream].Read(reader, bits); LoadFuncsFromDbiModule(bits, modules[m], names, funcList, readAllStrings, dir, nameIndex, reader); } } } var funcs = (PdbFunction[])funcList.ToArray(typeof(PdbFunction)); // After reading the functions, apply the token remapping table if it exists. if (header.snTokenRidMap != 0 && header.snTokenRidMap != 0xffff) { dir.streams[header.snTokenRidMap].Read(reader, bits); var ridMap = new uint[dir.streams[header.snTokenRidMap].Length / 4]; bits.ReadUInt32(ridMap); foreach (var func in funcs) { func.token = 0x06000000 | ridMap[func.token & 0xffffff]; } } //Array.Sort(funcs, PdbFunction.byAddress); Array.Sort(funcs, PdbFunction.byToken); return funcs; }
internal void Read(PdbReader reader, int position, byte[] bytes, int offset, int data) { if (position + data > contentSize) { throw new PdbException("DataStream can't read off end of stream. " + "(pos={0},siz={1})", position, data); } if (position == contentSize) { return; } int left = data; int page = position / reader.pageSize; int rema = position % reader.pageSize; // First get remained of first page. if (rema != 0) { int todo = reader.pageSize - rema; if (todo > left) { todo = left; } reader.Seek(pages[page], rema); reader.Read(bytes, offset, todo); offset += todo; left -= todo; page++; } // Now get the remaining pages. while (left > 0) { int todo = reader.pageSize; if (todo > left) { todo = left; } reader.Seek(pages[page], 0); reader.Read(bytes, offset, todo); offset += todo; left -= todo; page++; } }
internal MsfDirectory(PdbReader reader, PdbFileHeader head, BitAccess bits) { int pages = reader.PagesFromSize(head.directorySize); // 0..n in page of directory pages. bits.MinCapacity(head.directorySize); int directoryRootPages = head.directoryRoot.Length; int pagesPerPage = head.pageSize / 4; int pagesToGo = pages; for (int i = 0; i < directoryRootPages; i++) { int pagesInThisPage = pagesToGo <= pagesPerPage ? pagesToGo : pagesPerPage; reader.Seek(head.directoryRoot[i], 0); bits.Append(reader.reader, pagesInThisPage * 4); pagesToGo -= pagesInThisPage; } bits.Position = 0; DataStream stream = new DataStream(head.directorySize, bits, pages); bits.MinCapacity(head.directorySize); stream.Read(reader, bits); // 0..3 in directory pages int count; bits.ReadInt32(out count); // 4..n int[] sizes = new int[count]; bits.ReadInt32(sizes); // n..m streams = new DataStream[count]; for (int i = 0; i < count; i++) { if (sizes[i] <= 0) { streams[i] = new DataStream(); } else { streams[i] = new DataStream(sizes[i], bits, reader.PagesFromSize(sizes[i])); } } }
/// <summary> /// Returns a mutable Code Model assembly that is equivalent to the given Metadata Model assembly, /// except that in the new assembly method bodies also implement ISourceMethodBody. /// </summary> /// <param name="host">An object representing the application that is hosting this decompiler. It is used to obtain access to some global /// objects and services such as the shared name table and the table for interning references.</param> /// <param name="assembly">The root of the Metadata Model to be converted to a Code Model.</param> /// <param name="pdbReader">An object that can map offsets in an IL stream to source locations and block scopes. May be null.</param> /// <param name="options">Set of options that control decompilation.</param> public static Assembly GetCodeModelFromMetadataModel(IMetadataHost host, IAssembly assembly, PdbReader /*?*/ pdbReader, DecompilerOptions options = DecompilerOptions.None) { return((Assembly)GetCodeModelFromMetadataModelHelper(host, assembly, pdbReader, pdbReader, options)); }
internal SeparateContractsFromCode(IContractAwareHost host, PdbReader/*?*/ pdbReader, ILocalScopeProvider/*?*/ localScopeProvider, ContractProvider contractProvider) { this.contractAwareHost = host; this.pdbReader = pdbReader; this.localScopeProvider = localScopeProvider; this.contractProvider = contractProvider; this.TraverseIntoMethodBodies = true; }
public StatementCollector(PdbReader pdb) { statements = new List <IStatement>(); requireLocations = pdb != null; }
public static SourceCodeLocation OfMethod(this IMethodDefinition method, PdbReader pdb) { return(Of(method, pdb)); }
/// <summary> /// </summary> /// <param name="bits"> /// </param> /// <param name="info"> /// </param> /// <param name="names"> /// </param> /// <param name="funcList"> /// </param> /// <param name="readStrings"> /// </param> /// <param name="dir"> /// </param> /// <param name="nameIndex"> /// </param> /// <param name="reader"> /// </param> /// <exception cref="PdbDebugException"> /// </exception> private static void LoadFuncsFromDbiModule( BitAccess bits, DbiModuleInfo info, IntHashTable names, ArrayList funcList, bool readStrings, MsfDirectory dir, Dictionary<string, int> nameIndex, PdbReader reader) { PdbFunction[] funcs = null; bits.Position = 0; int sig; bits.ReadInt32(out sig); if (sig != 4) { throw new PdbDebugException("Invalid signature. (sig={0})", sig); } bits.Position = 4; // Console.WriteLine("{0}:", info.moduleName); funcs = PdbFunction.LoadManagedFunctions(info.moduleName, bits, (uint)info.cbSyms, readStrings); if (funcs != null) { bits.Position = info.cbSyms + info.cbOldLines; LoadManagedLines(funcs, names, bits, dir, nameIndex, reader, (uint)(info.cbSyms + info.cbOldLines + info.cbLines)); for (var i = 0; i < funcs.Length; i++) { funcList.Add(funcs[i]); } } }
private static bool PdbMatches(string pdb, Guid guid, int age) { PdbReader.GetPdbProperties(pdb, out Guid fileGuid, out int fileAge); return(guid == fileGuid); }
private static IPrimarySourceLocation GetValidLocation(this IObjectWithLocations locatable, PdbReader pdb) { return(pdb == null ? null : locatable.GetValidLocations(pdb).FirstOrDefault()); }
/// <summary> /// Generate the comparability information for the given assembly. /// </summary> private static AssemblySummary GenerateComparability(CeleriacArgs celeriacArgs, TypeManager typeManager, IMetadataHost host, IModule module, PdbReader pdbReader, ref Assembly mutable) { AssemblySummary comparabilityManager = null; IAssembly assembly = module as IAssembly; mutable = MetadataCopier.DeepCopy(host, assembly); typeManager.SetAssemblyIdentity(UnitHelper.GetAssemblyIdentity(mutable)); if (celeriacArgs.StaticComparability || celeriacArgs.GenerateComparability) { if (celeriacArgs.ComparabilityFile != null) { using (var cmp = File.Open(celeriacArgs.ComparabilityFile, FileMode.Open)) { comparabilityManager = (AssemblySummary) new BinaryFormatter().Deserialize(cmp); } } else { if (celeriacArgs.VerboseMode) { Console.WriteLine("Generating Comparability Information"); } Assembly decompiled = Decompiler.GetCodeModelFromMetadataModel(typeManager.Host, mutable, pdbReader, DecompilerOptions.AnonymousDelegates | DecompilerOptions.Iterators); comparabilityManager = AssemblySummary.MakeSummary(decompiled, typeManager); if (celeriacArgs.VerboseMode) { Console.WriteLine("Finished Generating Comparability Information"); } using (var cmp = File.Open(celeriacArgs.AssemblyPath + CeleriacArgs.ComparabilityFileExtension, FileMode.Create)) { new BinaryFormatter().Serialize(cmp, comparabilityManager); } } } return(comparabilityManager); }
public bool TrimBinaries(string sourceDir, string outputDir) { bool fSuccess = true; foreach (TrimAssembly trimAssembly in _includeSet.GetAllAssemblies()) { _currentTrimAssembly = trimAssembly; try { string sourceFile = Path.Combine(sourceDir, trimAssembly.Name + ".dll"); string outputFile = Path.Combine(outputDir, trimAssembly.Name + ".dll"); Console.WriteLine("loading assembly '" + sourceFile + "'"); IModule module = host.LoadUnitFrom(sourceFile) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { throw new Exception(sourceFile + " is not a PE file containing a CLR module or assembly, or an error occurred when loading it."); } // Working around bug DummyTraverser dummyTraverser = new DummyTraverser(); PdbReader pdbReader = null; PdbWriter pdbWriter = null; string pdbSourceFile = Path.ChangeExtension(sourceFile, "pdb"); string pdbOutputFile = Path.ChangeExtension(outputFile, "pdb"); if (File.Exists(pdbSourceFile)) { Stream pdbStream = File.OpenRead(pdbSourceFile); pdbReader = new PdbReader(pdbStream, host); pdbWriter = new PdbWriter(Path.GetFullPath(pdbOutputFile), pdbReader); } IAssembly /*?*/ assembly = module as IAssembly; if (assembly != null) { dummyTraverser.Visit(assembly); module = this.Rewrite(assembly); } else { dummyTraverser.Visit(module); module = this.Rewrite(module); } PeWriter.WritePeToStream(module, host, File.Create(outputFile), pdbReader, pdbReader, pdbWriter); } catch (Exception e) { Console.WriteLine(trimAssembly.Key + ": " + e.Message); throw; } } if (!fSuccess) { Console.Error.WriteLine(String.Format("At least one of the assemblies could not be processed!")); } return(fSuccess); }
private HermansAlwaysRight(IContractAwareHost contractAwareHost, ContractExtractor extractor, ISourceMethodBody sourceMethodBody, bool methodIsInReferenceAssembly, OldAndResultExtractor oldAndResultExtractor, PdbReader/*?*/ pdbReader) : base(contractAwareHost) { this.contractAwareHost = contractAwareHost; this.extractor = extractor; this.sourceMethodBody = sourceMethodBody; this.methodIsInReferenceAssembly = methodIsInReferenceAssembly; this.oldAndResultExtractor = oldAndResultExtractor; this.pdbReader = pdbReader; }
public static MethodContract/*?*/ ExtractContracts(IContractAwareHost contractAwareHost, PdbReader/*?*/ pdbReader, ContractExtractor extractor, ISourceMethodBody methodBody) { var definingUnit = TypeHelper.GetDefiningUnit(methodBody.MethodDefinition.ContainingType.ResolvedType); var methodIsInReferenceAssembly = ContractHelper.IsContractReferenceAssembly(contractAwareHost, definingUnit); var oldAndResultExtractor = new OldAndResultExtractor(contractAwareHost, methodBody, extractor.IsContractMethod); var localsInitializedWithFields = FindLocals.FindSetOfLocals(methodBody); var har = new HermansAlwaysRight(contractAwareHost, extractor, methodBody, methodIsInReferenceAssembly, oldAndResultExtractor, pdbReader); har.Rewrite(methodBody); if (har.extractor.currentMethodContract == null) return null; // The decompiler will have introduced locals if there were any anonymous delegates in the contracts // Such locals are initialized with the fields of the iterator class. // The contract that comes back from here will have those fields replaced with whatever the iterator captured // (parameters, locals). So the locals in the contract need to be replaced with the iterator fields so that // next replacement will see the right thing (i.e., the fields) and replace them! Phew! var localReplacer = new LocalReplacer(contractAwareHost, localsInitializedWithFields); localReplacer.Rewrite(har.extractor.currentMethodContract); // also need to rewrite the remainder of the body localReplacer.Rewrite(methodBody); return har.extractor.currentMethodContract; }
// TODO: First search the moveNextBody to see if there are any contracts at all. /// <summary> /// /// </summary> /// <param name="host"></param> /// <param name="extractor"></param> /// <param name="iteratorMethodBody"></param> /// <param name="moveNextBody"></param> /// <param name="pdbReader"></param> /// <returns></returns> public static MethodContract GetMethodContractFromMoveNext( IContractAwareHost host, ContractExtractor extractor, ISourceMethodBody iteratorMethodBody, ISourceMethodBody moveNextBody, PdbReader pdbReader ) { // Walk the iterator method and collect all of the state that is assigned to fields in the iterator class // That state needs to replace any occurrences of the fields in the contracts (if they exist...) var iteratorStmts = new List<IStatement>(iteratorMethodBody.Block.Statements); Dictionary<uint, IExpression> capturedThings = new Dictionary<uint, IExpression>(); // Find all of the state captured for the IEnumerable // REVIEW: Is this state ever used in the contracts? Since they're all sitting in the MoveNext // method, maybe they always use the IEnumerator state? if (1 < iteratorStmts.Count) { // First statement should be the creation of the iterator class int j = 1; while (j < iteratorStmts.Count) { var es = iteratorStmts[j++] as IExpressionStatement; if (es == null) break; var assign = es.Expression as IAssignment; if (assign == null) break; var field = assign.Target.Definition as IFieldReference; var capturedThing = assign.Source; var k = field.InternedKey; var spec = field as ISpecializedFieldReference; if (spec != null) k = spec.UnspecializedVersion.InternedKey; capturedThings.Add(k, capturedThing); } } else { var ret = iteratorStmts[0] as IReturnStatement; if (ret != null) { var be = ret.Expression as IBlockExpression; if (be != null) { var beStmts = new List<IStatement>(be.BlockStatement.Statements); var j = 1; while (j < beStmts.Count) { var es = beStmts[j++] as IExpressionStatement; if (es == null) break; var assign = es.Expression as IAssignment; if (assign == null) break; var field = assign.Target.Definition as IFieldReference; var capturedThing = assign.Source; var k = field.InternedKey; var spec = field as ISpecializedFieldReference; if (spec != null) k = spec.UnspecializedVersion.InternedKey; capturedThings.Add(k, capturedThing); } } } } // Find all of the state captured for the IEnumerator // That state is captured at the beginning of the IEnumerable<T>.GetEnumerator method IMethodDefinition getEnumerator = null; var t = moveNextBody.MethodDefinition.ContainingTypeDefinition; foreach (IMethodImplementation methodImplementation in t.ExplicitImplementationOverrides) { if (methodImplementation.ImplementedMethod.Name == host.NameTable.GetNameFor("GetEnumerator")) { var gtir = methodImplementation.ImplementedMethod.ContainingType as IGenericTypeInstanceReference; if (gtir != null && TypeHelper.TypesAreEquivalent(gtir.GenericType, host.PlatformType.SystemCollectionsGenericIEnumerable)) { getEnumerator = methodImplementation.ImplementingMethod.ResolvedMethod as IMethodDefinition; break; } } } if (getEnumerator != null) { IMethodBody geBody = getEnumerator.Body; var sourceGeBody = geBody as ISourceMethodBody; if (sourceGeBody == null) sourceGeBody = Decompiler.GetCodeModelFromMetadataModel(host, geBody, pdbReader, DecompilerOptions.AnonymousDelegates); foreach (var stmt in sourceGeBody.Block.Statements) { var es = stmt as IExpressionStatement; if (es == null) continue; var assign = es.Expression as IAssignment; if (assign == null) continue; var field2 = assign.Target.Definition as IFieldReference; if (field2 == null) continue; var k = field2.InternedKey; var spec = field2 as ISpecializedFieldReference; if (spec != null) k = spec.UnspecializedVersion.InternedKey; var sourceBe = assign.Source as IBoundExpression; if (sourceBe == null) continue; var field3 = sourceBe.Definition as IFieldReference; if (field3 == null) continue; var k3 = field3.InternedKey; var spec3 = field3 as ISpecializedFieldReference; if (spec3 != null) k3 = spec3.UnspecializedVersion.InternedKey; IExpression capturedThing = null; if (!capturedThings.TryGetValue(k3, out capturedThing)) continue; capturedThings[k] = capturedThing; } } var mc = HermansAlwaysRight.ExtractContracts(host, pdbReader, extractor, moveNextBody); if (mc == null) return mc; // substitute all field references in contract with the captured state var replacer = new Replacer(host, capturedThings, iteratorMethodBody.MethodDefinition, moveNextBody.MethodDefinition); replacer.RewriteChildren(mc); if (moveNextBody.MethodDefinition.ContainingTypeDefinition.IsGeneric) { var genericParameterMapper = new GenericMethodParameterMapper(host, iteratorMethodBody.MethodDefinition, moveNextBody.MethodDefinition.ContainingType as INestedTypeReference); mc = genericParameterMapper.Rewrite(mc) as MethodContract; } return mc; }
public static Bpl.Program /*?*/ TranslateAssembly(List <string> assemblyNames, HeapFactory heapFactory, Options options, List <Regex> exemptionList, bool whiteList) { Contract.Requires(assemblyNames != null); Contract.Requires(heapFactory != null); var libPaths = options.libpaths; var wholeProgram = options.wholeProgram; var /*?*/ stubAssemblies = options.stub; var host = new CodeContractAwareHostEnvironment(libPaths != null ? libPaths : Enumerable <string> .Empty, true, true); Host = host; Bpl.CommandLineOptions.Install(new Bpl.CommandLineOptions()); #region Assemlies to translate (via cmd line) modules = new List <IModule>(); var contractExtractors = new Dictionary <IUnit, IContractProvider>(); var pdbReaders = new Dictionary <IUnit, PdbReader>(); #region Load *all* of the assemblies before doing anything else so that they can all vote on unification matters foreach (var a in assemblyNames) { var module = host.LoadUnitFrom(a) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { Console.WriteLine(a + " is not a PE file containing a CLR module or assembly, or an error occurred when loading it."); Console.WriteLine("Skipping it, continuing with other input assemblies"); continue; } modules.Add(module); } #endregion #region Decompile all of the assemblies var decompiledModules = new List <IModule>(); foreach (var m in modules) { PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(m.Location, "pdb"); if (File.Exists(pdbFile)) { Stream pdbStream = File.OpenRead(pdbFile); pdbReader = new PdbReader(pdbStream, host); } var m2 = Decompiler.GetCodeModelFromMetadataModel(host, m, pdbReader, DecompilerOptions.Unstack) as IModule; // The decompiler does not turn calls to Assert/Assume into Code Model nodes m2 = new Microsoft.Cci.MutableContracts.ContractExtractor.AssertAssumeExtractor(host, pdbReader).Rewrite(m2); decompiledModules.Add(m2); host.RegisterAsLatest(m2); contractExtractors.Add(m2, host.GetContractExtractor(m2.UnitIdentity)); pdbReaders.Add(m2, pdbReader); } modules = decompiledModules; #endregion #endregion #region Assemblies to translate (stubs) if (stubAssemblies != null) { foreach (var s in stubAssemblies) { var module = host.LoadUnitFrom(s) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { Console.WriteLine(s + " is not a PE file containing a CLR module or assembly, or an error occurred when loading it."); Console.WriteLine("Skipping it, continuing with other input assemblies"); } PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { Stream pdbStream = File.OpenRead(pdbFile); pdbReader = new PdbReader(pdbStream, host); } module = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader, DecompilerOptions.Unstack) as IModule; var copier = new CodeDeepCopier(host); var mutableModule = copier.Copy(module); var mscorlib = TypeHelper.GetDefiningUnit(host.PlatformType.SystemObject.ResolvedType); //var mutator = new ReparentModule(host, mscorlib, mutableModule); //module = mutator.Rewrite(mutableModule); //modules.Add(Tuple.Create(module, pdbReader)); RewriteUnitReferences renamer = new RewriteUnitReferences(host, mutableModule); var mscorlibAssembly = (IAssembly)mscorlib; renamer.targetAssembly = mscorlibAssembly; renamer.originalAssemblyIdentity = mscorlibAssembly.AssemblyIdentity; renamer.RewriteChildren(mutableModule); modules.Add((IModule)mutableModule); contractExtractors.Add(module, host.GetContractExtractor(module.UnitIdentity)); pdbReaders.Add(module, pdbReader); } } #endregion if (modules.Count == 0) { throw new TranslationException("No input assemblies to translate."); } //var primaryModule = modules[0]; Sink sink = new Sink(host, heapFactory, options, exemptionList, whiteList); TranslationHelper.tmpVarCounter = 0; // TODO move away, get all plugin and translators from a config file or alike #region Plugged translators List <Translator> translatorsPlugged = new List <Translator>(); ITranslationPlugin bctPlugin = new BytecodeTranslatorPlugin(wholeProgram); Translator bcTranslator = bctPlugin.getTranslator(sink, contractExtractors, pdbReaders); translatorsPlugged.Add(bcTranslator); #endregion sink.TranslationPlugins = translatorsPlugged; // TODO replace the whole translation by a translator initialization and an orchestrator calling back for each element // TODO for the current BC translator it will possibly just implement onMetadataElement(IModule) // TODO refactor this away, handle priorities between plugged translators IOrderedEnumerable <Translator> prioritizedTranslators = translatorsPlugged.OrderBy(t => t.getPriority()); foreach (Translator t in prioritizedTranslators) { t.initialize(); if (t.isOneShot()) { t.TranslateAssemblies(modules); } } foreach (var pair in sink.delegateTypeToDelegates.Values) { CreateDispatchMethod(sink, pair.Item1, pair.Item2); CreateDelegateCreateMethod(sink, pair.Item1, pair.Item2); CreateDelegateAddMethod(sink, pair.Item1, pair.Item2); CreateDelegateRemoveMethod(sink, pair.Item1, pair.Item2); } // Subtyping for extern types if (sink.Options.typeInfo > 0) { sink.DeclareExternTypeSubtyping(); } //sink.CreateIdentifierCorrespondenceTable(primaryModule.Name.Value); //var rc = new Bpl.ResolutionContext((Bpl.IErrorSink)null); //foreach (var decl in sink.TranslatedProgram.TopLevelDeclarations) { // decl.Register(rc); //} //sink.TranslatedProgram.Resolve(rc); //var goodDecls = new List<Bpl.Declaration>(); //var tc = new Bpl.TypecheckingContext(null); //foreach (var decl in sink.TranslatedProgram.TopLevelDeclarations) { // var impl = decl as Bpl.Implementation; // if (impl == null) { // goodDecls.Add(decl); // continue; // } // try { // //var tc = new Bpl.TypecheckingContext(null); // impl.Typecheck(tc); // goodDecls.Add(impl); // } catch { // Console.WriteLine("Deleting implementation for: " + impl.Name); // // nothing to do, just continue // } //} //sink.TranslatedProgram.TopLevelDeclarations = goodDecls; return(sink.TranslatedProgram); }
public CodeModelRoundTripTests() { pdbReader = null; pdbWriter = null; host = new HostEnvironment(); }
/// <summary> /// Returns a (mutable) Code Model SourceMethod body that is equivalent to the given Metadata Model method body. /// It does *not* delete any helper types. /// </summary> /// <param name="host">An object representing the application that is hosting this decompiler. It is used to obtain access to some global /// objects and services such as the shared name table and the table for interning references.</param> /// <param name="methodBody">The Metadata Model method body that is to be decompiled.</param> /// <param name="pdbReader">An object that can map offsets in an IL stream to source locations and block scopes. May be null.</param> /// <param name="options">Set of options that control decompilation.</param> public static ISourceMethodBody GetCodeModelFromMetadataModel(IMetadataHost host, IMethodBody methodBody, PdbReader /*?*/ pdbReader, DecompilerOptions options = DecompilerOptions.None) { return(new Microsoft.Cci.ILToCodeModel.SourceMethodBody(methodBody, host, pdbReader, pdbReader, options)); }
static void Main(string[] args) { String inputFile; String targetFile; String targetNamespace; String targetClass; String targetMethod; int depth; int dimension; int numberValidPaths; int duplicateBasicBlockWeight; int duplicateBasicBlockCorrectionValue; int stateChangeWeight; int stateChangeCorrectionValue; int insertOpaquePredicateWeight; int seed; // Add debugging code into the obfuscated method (dump obfuscation graphs and so on) bool graphTransformerDebug = false; // Should the obfuscated code contain information to trace the control flow? bool basicBlockTrace = false; // When debugging is active, should the whole obfuscation graph be dumped or only the vpaths in it? bool graphOnlyDumpVPaths = true; // The number of random interfaces that are added to the program int numberRandomInterfaces = 100; if (args.Length != 14) { System.Console.WriteLine("Needed parameters: <inputBinary> <outputBinary> <namespace> <class> <method> <depth> <dimension> <numberValidPaths> <duplicateBasicBlockWeight> <duplicateBasicBlockCorrectionValue> <stateChangeWeight> <stateChangeCorrectionValue> <insertOpaquePredicateWeight> <seed>"); return; } else { inputFile = args[0]; targetFile = args[1]; targetNamespace = args[2]; targetClass = args[3]; targetMethod = args[4]; depth = Convert.ToInt32(args[5]); dimension = Convert.ToInt32(args[6]); numberValidPaths = Convert.ToInt32(args[7]); duplicateBasicBlockWeight = Convert.ToInt32(args[8]); duplicateBasicBlockCorrectionValue = Convert.ToInt32(args[9]); stateChangeWeight = Convert.ToInt32(args[10]); stateChangeCorrectionValue = Convert.ToInt32(args[11]); insertOpaquePredicateWeight = Convert.ToInt32(args[12]); seed = Convert.ToInt32(args[13]); } String logDir = Path.GetDirectoryName(targetFile); Log.Log logger = new Log.Log(logDir, "probfuscation_logfile.txt"); System.Console.WriteLine("Obfuscating: " + inputFile); logger.writeLine("Obfuscating: " + inputFile); System.Console.WriteLine("Output file: " + targetFile); logger.writeLine("Output file: " + targetFile); System.Console.WriteLine("Target namespace: " + targetNamespace); logger.writeLine("Target namespace: " + targetNamespace); System.Console.WriteLine("Target class: " + targetClass); logger.writeLine("Target class: " + targetClass); System.Console.WriteLine("Target method: " + targetMethod); logger.writeLine("Target method: " + targetMethod); System.Console.WriteLine("Depth: " + depth); logger.writeLine("Depth: " + depth); System.Console.WriteLine("Dimension: " + dimension); logger.writeLine("Dimension: " + dimension); System.Console.WriteLine("Number of vpaths: " + numberValidPaths); logger.writeLine("Number of vpaths: " + numberValidPaths); System.Console.WriteLine("Basic Block duplication weight: " + duplicateBasicBlockWeight); logger.writeLine("Basic Block duplication weight: " + duplicateBasicBlockWeight); System.Console.WriteLine("Basic Block duplication correction value: " + duplicateBasicBlockCorrectionValue); logger.writeLine("Basic Block duplication correction value: " + duplicateBasicBlockCorrectionValue); System.Console.WriteLine("State change weight: " + stateChangeWeight); logger.writeLine("State change weight: " + stateChangeWeight); System.Console.WriteLine("State change correction value: " + stateChangeCorrectionValue); logger.writeLine("State change correction value: " + stateChangeCorrectionValue); System.Console.WriteLine("Opaque predicate weight: " + insertOpaquePredicateWeight); logger.writeLine("Opaque predicate weight: " + insertOpaquePredicateWeight); System.Console.WriteLine("Seed: " + seed); logger.writeLine("Seed: " + seed); // Seed PRNG for interfaces PRNGRandomInterfaces = new Random(seed); using (var host = new PeReader.DefaultHost()) { IModule /*?*/ module = host.LoadUnitFrom(inputFile) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { Console.WriteLine(inputFile + " is not a PE file containing a CLR module or assembly."); return; } module = new MetadataDeepCopier(host).Copy(module); if (module as Assembly == null) { logger.writeLine("File does not have CIL assembly"); return; } // create analyzer object object CfgBuilder analyze = new Cfg.CfgBuilder(module, host, logger); PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } else { logger.writeLine("Could not load the PDB file for '" + module.Name.Value + "' . Proceeding anyway."); } using (pdbReader) { Microsoft.Cci.ILGenerator.LocalScopeProvider localScopeProvider = null; if (pdbReader != null) { localScopeProvider = new ILGenerator.LocalScopeProvider(pdbReader); } // search the namespace the interface should be added to IUnitNamespace foundNamespace = null; foreach (var tempMember in module.UnitNamespaceRoot.Members) { if ((tempMember as IUnitNamespace) == null) { continue; } IUnitNamespace tempNamespace = (tempMember as IUnitNamespace); if (tempNamespace.ToString() == targetNamespace) { foundNamespace = tempNamespace; break; } } if (foundNamespace == null) { throw new ArgumentException("Not able to find target namespace."); } // add created interface (and implemented methods) to all classes bool classFound = false; foreach (var tempClass in module.GetAllTypes()) { if ((tempClass as NamespaceTypeDefinition) == null || tempClass.IsAbstract) { continue; } NamespaceTypeDefinition foundClass = (tempClass as NamespaceTypeDefinition); if (foundClass.ContainingUnitNamespace.ToString() == "") { continue; } if (foundClass.ToString() != targetNamespace + "." + targetClass) { continue; } classFound = true; Random prng = new Random(); GraphTransformer graphTransformer = new GraphTransformer(module, host, logger, prng, foundNamespace, foundClass, depth, dimension, graphTransformerDebug); graphTransformer.duplicateBasicBlockWeight = duplicateBasicBlockWeight; graphTransformer.duplicateBasicBlockCorrectionValue = duplicateBasicBlockCorrectionValue; graphTransformer.stateChangeWeight = stateChangeWeight; graphTransformer.stateChangeCorrectionValue = stateChangeCorrectionValue; graphTransformer.insertOpaquePredicateWeight = insertOpaquePredicateWeight; graphTransformer.trace = basicBlockTrace; graphTransformer.graphOnlyDumpVPaths = graphOnlyDumpVPaths; graphTransformer.debuggingDumpLocation = logDir; // Add 100 random interfaces to the namespace Helper testHelper = new Helper(module, host, logger); List <NamespaceTypeDefinition> randomInterfaces = new List <NamespaceTypeDefinition>(); for (int i = 0; i < numberRandomInterfaces; i++) { String randName = randomString(20); NamespaceTypeDefinition temp = testHelper.createNewInterface(randName, foundNamespace); randomInterfaces.Add(temp); } InterfaceTransformer interfaceTransformer = new InterfaceTransformer(module, host, logger); foreach (var classToAdd in module.GetAllTypes()) { if ((classToAdd as NamespaceTypeDefinition) == null || classToAdd.IsAbstract || classToAdd.IsInterface || classToAdd.IsEnum || classToAdd.IsDelegate || classToAdd.IsGeneric || classToAdd.IsStruct) { continue; } if (((NamespaceTypeDefinition)classToAdd).ContainingUnitNamespace.ToString() == "") { continue; } /* * // Use this code if you want to add standard interfaces to the target class * interfaceTransformer.addStdInterfacesGivenByFile(@"e:\code\dotnet_standard_interfaces.txt"); * * // add std interfaces to class * if (foundClass != (classToAdd as NamespaceTypeDefinition)) { * foreach (ITypeDefinition temp in interfaceTransformer.getInterfacesList()) { * interfaceTransformer.addInterface((classToAdd as NamespaceTypeDefinition), temp); * } * } */ // Add random interfaces to the classes List <NamespaceTypeDefinition> alreadyAdded = new List <NamespaceTypeDefinition>(); int max = PRNGRandomInterfaces.Next(numberRandomInterfaces); NamespaceTypeDefinition interfaceClass = (classToAdd as NamespaceTypeDefinition); logger.writeLine("Adding " + max + " random interfaces to class \"" + interfaceClass.ToString() + "\""); for (int i = 0; i < max; i++) { NamespaceTypeDefinition randInterface = randomInterfaces.ElementAt(PRNGRandomInterfaces.Next(randomInterfaces.Count)); if (alreadyAdded.Contains(randInterface)) { continue; } alreadyAdded.Add(randInterface); logger.writeLine("Adding interface: \"" + randInterface.ToString() + "\""); // add nodes interface to class if (interfaceClass.Interfaces != null) { interfaceClass.Interfaces.Add(randInterface); } else { interfaceClass.Interfaces = new List <ITypeReference>(); interfaceClass.Interfaces.Add(randInterface); } } logger.writeLine(""); // Add special interface for the obfuscation scheme to the class // (makes sure that all needed attributes and methods are implemented) graphTransformer.addNodeInterfaceToTargetClass((classToAdd as NamespaceTypeDefinition)); } // Prepare obfuscation graph graphTransformer.generateGraph(numberValidPaths); graphTransformer.createGraphMethods(); // Search method to obfuscate MethodDefinition methodToObfu = null; foreach (MethodDefinition tempMethod in foundClass.Methods) { if (tempMethod.Name.ToString() == targetMethod) { methodToObfu = tempMethod; break; } } if (methodToObfu == null) { throw new ArgumentException("Not able to find target method."); } // Obfuscate target method MethodCfg cfg = analyze.buildCfgForMethod(methodToObfu); logger.dumpMethodCfg(cfg, "before"); graphTransformer.addObfuscationToMethod(cfg); analyze.createMethodFromCfg(cfg); logger.dumpMethodCfg(cfg, "after"); break; } if (!classFound) { throw new ArgumentException("Not able to find target class."); } /* * This code can be used if not only one specific method should be obfuscated, * but the whole class. * List<ClassCfg> classCfgList = new List<ClassCfg>(); * foreach (var tempClass in module.GetAllTypes()) { * if ((tempClass as NamespaceTypeDefinition) == null || tempClass.IsAbstract) { || continue; || } || || // create basic blocks || NamespaceTypeDefinition foundClass = (tempClass as NamespaceTypeDefinition); || || logger.writeLine("Create CFG for class \"" + foundClass.Name.ToString() + "\""); || ClassCfg temp = analyze.buildCfgForClass(foundClass); || classCfgList.Add(temp); || logger.writeLine("\n---------------------------------\n"); ||} || ||// transform each function ||NopTransformer transformator = new NopTransformer(module, host, logger); ||foreach (ClassCfg tempClassCfg in classCfgList) { || foreach (MethodCfg tempMethodCfg in tempClassCfg.methodCfgs) { || logger.writeLine("Transform method CFG of \"" + tempMethodCfg.method.ToString() + "\""); || transformator.addNopsToCfg(tempMethodCfg); || logger.writeLine("\n---------------------------------\n"); || } ||} || ||foreach (ClassCfg tempClassCfg in classCfgList) { || logger.writeLine("Create class from CFG for \"" + tempClassCfg.classObj.Name.ToString() + "\""); || analyze.createClassFromCfg(tempClassCfg); || logger.writeLine("\n---------------------------------\n"); ||} */ using (var peStream = File.Create(targetFile)) { using (var pdbWriter = new PdbWriter(Path.ChangeExtension(targetFile, ".pdb"), pdbReader)) { PeWriter.WritePeToStream(module, host, peStream, pdbReader, localScopeProvider, pdbWriter); } } } } }
/// <summary> /// Amends the specified target assembly, optionally using assembly amendments defined in the /// specified amendment assemblies. /// </summary> /// <param name="targetAssembly"></param> /// <param name="amendmentAssemblies"></param> internal static void Amend(string targetAssembly, string[] amendmentAssemblies, string[] referenceAssemblies) { // Verify the target assembly exists targetAssembly = Path.GetFullPath(targetAssembly); if (!File.Exists(targetAssembly)) { throw new ArgumentException("The specified target assembly, " + targetAssembly + ", does not exist."); } // Verify the amendment assemblies exist if (amendmentAssemblies == null) { amendmentAssemblies = new string[0]; } for (int i = 0; i < amendmentAssemblies.Length; i++) { var path = amendmentAssemblies[i] = Path.GetFullPath(amendmentAssemblies[i]); if (!File.Exists(path)) { throw new ArgumentException("The specified amendment assembly, " + path + ", does not exist."); } } // Verify that the target has not already been amended var afterthoughtTracker = targetAssembly + ".afterthought"; if (File.Exists(afterthoughtTracker) && File.GetLastWriteTime(targetAssembly) == File.GetLastWriteTime(afterthoughtTracker)) { return; } // Determine the set of target directories and backup locations var targetWriteTime = File.GetLastWriteTime(targetAssembly); var backupTargetAssembly = targetAssembly + ".backup"; var targetDirectory = Path.GetDirectoryName(targetAssembly); File.Delete(backupTargetAssembly); File.Move(targetAssembly, backupTargetAssembly); // Build up a set of paths with resolving assemblies var referencePaths = new Dictionary <string, string>(); foreach (string path in amendmentAssemblies .Union(referenceAssemblies) .Union(Directory.GetFiles(targetDirectory).Where(p => p.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) && p != targetAssembly))) { referencePaths[Path.GetFileName(path)] = path; } // Register an assembly resolver to look in assembly directories when resolving assemblies AppDomain.CurrentDomain.AssemblyResolve += (s, e) => { var assemblyName = new System.Reflection.AssemblyName(e.Name).Name + ".dll"; string referencePath; if (referencePaths.TryGetValue(assemblyName, out referencePath)) { return(System.Reflection.Assembly.LoadFrom(referencePath)); } return(null); }; // Get the set of amendments to apply from all of the specified assemblies var assemblies = new System.Reflection.Assembly[] { System.Reflection.Assembly.LoadFrom(backupTargetAssembly) }.Union(amendmentAssemblies.Select(a => System.Reflection.Assembly.LoadFrom(a))); var amendments = AmendmentAttribute.GetAmendments(assemblies.First(), assemblies.Skip(1).ToArray()).ToList(); // Exit immediately if there are no amendments in the target assemblies //if (amendments.Count == 0) // return; // Amend the target assembly Console.Write("Amending " + Path.GetFileName(targetAssembly)); var start = DateTime.Now; using (var host = new PeReader.DefaultHost()) { // Load the target assembly IModule module = host.LoadUnitFrom(backupTargetAssembly) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { throw new ArgumentException(backupTargetAssembly + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); } // Copy the assembly to enable it to be mutated module = new MetadataDeepCopier(host).Copy(module); // Load the debug file if it exists PdbReader pdbReader = null; var pdbFile = Path.Combine(targetDirectory, Path.GetFileNameWithoutExtension(targetAssembly) + ".pdb"); var backupPdbFile = pdbFile + ".backup"; if (File.Exists(pdbFile)) { File.Delete(backupPdbFile); File.Move(pdbFile, backupPdbFile); using (var pdbStream = File.OpenRead(backupPdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } // Amend and persist the target assembly using (pdbReader) { // Create and execute a new assembly amender AssemblyAmender amender = new AssemblyAmender(host, pdbReader, amendments, assemblies); amender.TargetRuntimeVersion = module.TargetRuntimeVersion; module = amender.Visit(module); // Save the amended assembly back to the original directory var localScopeProvider = pdbReader == null ? null : new ILGenerator.LocalScopeProvider(pdbReader); using (var pdbWriter = pdbReader != null ? new PdbWriter(pdbFile, pdbReader) : null) { using (var dllStream = File.Create(targetAssembly)) { PeWriter.WritePeToStream(module, host, dllStream, pdbReader, localScopeProvider, pdbWriter); } } } File.SetLastWriteTime(targetAssembly, targetWriteTime); if (pdbReader != null) { File.SetLastWriteTime(pdbFile, targetWriteTime); } } Console.WriteLine(" (" + DateTime.Now.Subtract(start).TotalSeconds.ToString("0.000") + " seconds)"); // Set the last write time of the afterthought tracker to match the amended assembly to prevent accidental reamending File.WriteAllText(afterthoughtTracker, ""); File.SetLastWriteTime(afterthoughtTracker, File.GetLastWriteTime(targetAssembly)); }
internal static void Amend(params string[] targets) { // Ensure that at least one target assembly was specified if (targets == null || targets.Length == 0) { throw new ArgumentException("At least one target assembly must be specified."); } // Ensure that the target assemblies exist foreach (var path in targets) { if (!File.Exists(path)) { throw new ArgumentException("The specified target assembly, " + path + ", does not exist."); } } // Determine the set of target directories and backup locations var directories = targets .Select(path => Path.GetDirectoryName(path).ToLower()) .Distinct() .Select(directory => new { SourcePath = directory, BackupPath = Directory.CreateDirectory(Path.Combine(directory, "Backup")).FullName }); // Determine the set of dlls, pdbs, and backup files var assemblies = targets .Select(dllPath => new { DllPath = dllPath, DllBackupPath = Path.Combine(Path.Combine(Path.GetDirectoryName(dllPath), "Backup"), Path.GetFileName(dllPath)), PdbPath = Path.Combine(Path.GetDirectoryName(dllPath), Path.GetFileNameWithoutExtension(dllPath) + ".pdb"), PdbBackupPath = Path.Combine(Path.Combine(Path.GetDirectoryName(dllPath), "Backup"), Path.GetFileNameWithoutExtension(dllPath) + ".pdb") }); // Backup the directories containing the targeted dll and pdb files foreach (var directory in directories) { foreach (var file in Directory.GetFiles(directory.SourcePath)) { if (file.ToLower().EndsWith("exe") || file.ToLower().EndsWith("dll") || file.ToLower().EndsWith("pdb")) { File.Copy(file, Path.Combine(directory.BackupPath, Path.GetFileName(file)), true); } } } // Register an assembly resolver to look in backup folders when resolving assemblies AppDomain.CurrentDomain.AssemblyResolve += (s, e) => { try { return(System.Reflection.Assembly.Load(e.Name)); } catch { foreach (var directory in directories) { var dependency = Path.Combine(directory.BackupPath, e.Name.Substring(0, e.Name.IndexOf(',')) + ".dll"); if (File.Exists(dependency)) { return(System.Reflection.Assembly.LoadFrom(dependency)); } } return(null); } }; // Get the set of amendments to apply from all of the specified assemblies var amendments = assemblies.SelectMany(a => AmendmentAttribute.GetAmendments(System.Reflection.Assembly.LoadFrom(a.DllBackupPath))).ToList(); // Exit immediately if there are no amendments in the target assemblies if (amendments.Count == 0) { return; } // Process each target assembly individually foreach (var assembly in assemblies) { Console.Write("Amending " + Path.GetFileName(assembly.DllPath)); var start = DateTime.Now; using (var host = new PeReader.DefaultHost()) { // Load the target assembly IModule module = host.LoadUnitFrom(assembly.DllBackupPath) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { throw new ArgumentException(assembly.DllBackupPath + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); } // Copy the assembly to enable it to be mutated module = MetadataCopier.DeepCopy(host, module); // Load the debug file if it exists PdbReader pdbReader = null; if (File.Exists(assembly.PdbBackupPath)) { using (var pdbStream = File.OpenRead(assembly.PdbBackupPath)) { pdbReader = new PdbReader(pdbStream, host); } } // Amend and persist the target assembly using (pdbReader) { // Create and execute a new assembly amender AssemblyAmender amender = new AssemblyAmender(host, pdbReader, amendments); amender.TargetRuntimeVersion = module.TargetRuntimeVersion; module = amender.Visit(module); // Save the amended assembly back to the original directory using (var pdbWriter = pdbReader != null ? new PdbWriter(assembly.PdbPath, pdbReader) : null) { using (var dllStream = File.Create(assembly.DllPath)) { PeWriter.WritePeToStream(module, host, dllStream, pdbReader, null, pdbWriter); } } } } Console.WriteLine(" (" + DateTime.Now.Subtract(start).TotalSeconds.ToString("0.000") + " seconds)"); } }
/// <summary> /// Given a mutable module that is a "declarative" module, i.e., it has contracts expressed as contract calls /// at the beginning of method bodies, this method will extract them, leaving the method bodies without those /// calls and return a contract provider for the module containing any extracted contracts. /// </summary> public static ContractProvider ExtractContracts(IContractAwareHost host, Module module, PdbReader/*?*/ pdbReader, ILocalScopeProvider/*?*/ localScopeProvider) { var contractMethods = new ContractMethods(host); var cp = new Microsoft.Cci.MutableContracts.ContractProvider(contractMethods, module); var extractor = new SeparateContractsFromCode(host, pdbReader, localScopeProvider, cp); extractor.Traverse(module); return cp; }
static void Main(string[] args) { if (args == null || args.Length == 0) { Console.WriteLine("usage: PeToPe [path]fileName.ext [decompile] [noStack]"); return; } bool decompile = args.Length >= 2; bool noStack = args.Length >= 3; using (var host = new HostEnvironment()) { //Read the Metadata Model from the PE file var module = host.LoadUnitFrom(args[0]) as IModule; if (module == null || module is Dummy) { Console.WriteLine(args[0] + " is not a PE file containing a CLR module or assembly."); return; } //Get a PDB reader if there is a PDB file. PdbReader /*?*/ pdbReader = null; string pdbFile = module.DebugInformationLocation; if (string.IsNullOrEmpty(pdbFile) || !File.Exists(pdbFile)) { pdbFile = Path.ChangeExtension(module.Location, "pdb"); } if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { pdbReader = new PdbReader(pdbStream, host); } } using (pdbReader) { ISourceLocationProvider sourceLocationProvider = pdbReader; ILocalScopeProvider localScopeProvider = pdbReader; if (decompile) { //Construct a Code Model from the Metadata model via decompilation var options = DecompilerOptions.AnonymousDelegates | DecompilerOptions.Iterators | DecompilerOptions.Loops; if (noStack) { options |= DecompilerOptions.Unstack; } module = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader, options); if (pdbReader != null) { localScopeProvider = new Decompiler.LocalScopeProvider(pdbReader); } } MetadataRewriter rewriter; MetadataDeepCopier copier; if (decompile) { copier = new CodeDeepCopier(host, pdbReader, pdbReader); rewriter = new CodeRewriter(host); } else { copier = new MetadataDeepCopier(host); rewriter = new MetadataRewriter(host); } var mutableModule = copier.Copy(module); module = rewriter.Rewrite(mutableModule); //var validator = new MetadataValidator(host); //List<Microsoft.Cci.ErrorEventArgs> errorEvents = new List<Microsoft.Cci.ErrorEventArgs>(); //host.Errors += (object sender, Microsoft.Cci.ErrorEventArgs e) => errorEvents.Add(e); //var assem = module as IAssembly; //validator.Validate(assem); //if (errorEvents.Count != 0) //{ // foreach (var e in errorEvents) // { // foreach (var err in e.Errors) // { // Console.WriteLine(err.Message); // } // } //} #if DEBUG var newRoot = Path.GetFileNameWithoutExtension(module.Location) + "1"; var newName = newRoot + Path.GetExtension(module.Location); using (Stream peStream = File.Create(newName)) { if (pdbReader == null) { PeWriter.WritePeToStream(module, host, peStream); } else { using (var pdbWriter = new PdbWriter(newRoot + ".pdb", pdbReader, emitTokenSourceInfo: true)) { PeWriter.WritePeToStream(module, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter); } } } #else using (Stream peStream = File.Create(module.Location)) { if (pdbReader == null) { PeWriter.WritePeToStream(module, host, peStream); } else { using (var pdbWriter = new PdbWriter(pdbFile, pdbReader, emitTokenSourceInfo: true)) { PeWriter.WritePeToStream(module, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter); } } } #endif } } }
private static IEnumerable <IPrimarySourceLocation> GetValidLocations(this IObjectWithLocations locatable, PdbReader pdb) { return(from l in pdb.GetPrimarySourceLocationsFor(locatable.Locations) where l.Length != 0 select l); }
public SourceEmitter(ISourceEmitterOutput sourceEmitterOutput, IMetadataHost host, PdbReader /*?*/ pdbReader, bool noIL, bool printCompilerGeneratedMembers, bool noStack) : base(sourceEmitterOutput) { this.host = host; this.pdbReader = pdbReader; this.noIL = noIL; this.printCompilerGeneratedMembers = printCompilerGeneratedMembers; this.noStack = noStack; }
static void Main(string[] args) { if (args == null || args.Length == 0) { Console.WriteLine("usage: PeToPe [path]fileName.ext [noStack]"); return; } bool noStack = args.Length == 2; using (var host = new PeReader.DefaultHost()) { //Read the Metadata Model from the PE file var module = host.LoadUnitFrom(args[0]) as IModule; if (module == null || module == Dummy.Module || module == Dummy.Assembly) { Console.WriteLine(args[0] + " is not a PE file containing a CLR module or assembly."); return; } //Get a PDB reader if there is a PDB file. PdbReader /*?*/ pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { Stream pdbStream = File.OpenRead(pdbFile); pdbReader = new PdbReader(pdbStream, host); } using (pdbReader) { //Construct a Code Model from the Metadata model via decompilation var options = DecompilerOptions.None; if (noStack) { options |= DecompilerOptions.Unstack; } var decompiledModule = Decompiler.GetCodeModelFromMetadataModel(host, module, pdbReader, options); ISourceLocationProvider sourceLocationProvider = pdbReader; //The decompiler preserves the Locations from the IOperation values, so the PdbReader still works. //Recompiling the CodeModel to IL might change the IL offsets, so a new provider is needed. ILocalScopeProvider localScopeProvider = new Decompiler.LocalScopeProvider(pdbReader); //Get a mutable copy of the Code Model. The ISourceLocationProvider is needed to provide copied source method bodies with the //ability to find out where to mark sequence points when compiling themselves back into IL. //(ISourceMethodBody does not know about the Source Model, so this information must be provided explicitly.) var copier = new CodeDeepCopier(host, sourceLocationProvider); var mutableModule = copier.Copy(decompiledModule); //Traverse the mutable copy. In a real application the traversal will collect information to be used during rewriting. var traverser = new CodeTraverser() { PreorderVisitor = new CodeVisitor() }; traverser.Traverse(mutableModule); //Rewrite the mutable Code Model. In a real application CodeRewriter would be a subclass that actually does something. //(This is why decompiled source method bodies must recompile themselves, rather than just use the IL from which they were decompiled.) var rewriter = new CodeRewriter(host); var rewrittenModule = rewriter.Rewrite(mutableModule); //Write out the Code Model by traversing it as the Metadata Model that it also is. using (var peStream = File.Create(rewrittenModule.Location + ".pe")) { if (pdbReader == null) { PeWriter.WritePeToStream(rewrittenModule, host, peStream); } else { using (var pdbWriter = new PdbWriter(rewrittenModule.Location + ".pdb", pdbReader)) { PeWriter.WritePeToStream(rewrittenModule, host, peStream, sourceLocationProvider, localScopeProvider, pdbWriter); } } } } } }
public SourceLocator(string modulePath) { LocationsByToken = new Dictionary <uint, IEnumerable <CciMethodLine> >(); PdbReader = new PdbReader(modulePath); PopulateSourceLocations(); }
/// <summary> /// </summary> /// <param name="funcs"> /// </param> /// <param name="names"> /// </param> /// <param name="bits"> /// </param> /// <param name="dir"> /// </param> /// <param name="nameIndex"> /// </param> /// <param name="reader"> /// </param> /// <param name="limit"> /// </param> private static void LoadManagedLines( PdbFunction[] funcs, IntHashTable names, BitAccess bits, MsfDirectory dir, Dictionary<string, int> nameIndex, PdbReader reader, uint limit) { Array.Sort(funcs, PdbFunction.byAddress); var checks = new IntHashTable(); // Read the files first var begin = bits.Position; while (bits.Position < limit) { int sig; int siz; bits.ReadInt32(out sig); bits.ReadInt32(out siz); var place = bits.Position; var endSym = bits.Position + siz; switch ((DEBUG_S_SUBSECTION)sig) { case DEBUG_S_SUBSECTION.FILECHKSMS: while (bits.Position < endSym) { CV_FileCheckSum chk; var ni = bits.Position - place; bits.ReadUInt32(out chk.name); bits.ReadUInt8(out chk.len); bits.ReadUInt8(out chk.type); var name = (string)names[(int)chk.name]; int guidStream; var doctypeGuid = SymDocumentType.Text; var languageGuid = SymLanguageType.CSharp; var vendorGuid = SymLanguageVendor.Microsoft; if (nameIndex.TryGetValue("/src/files/" + name, out guidStream)) { var guidBits = new BitAccess(0x100); dir.streams[guidStream].Read(reader, guidBits); LoadGuidStream(guidBits, out doctypeGuid, out languageGuid, out vendorGuid); } var src = new PdbSource((uint)ni, name, doctypeGuid, languageGuid, vendorGuid); checks.Add(ni, src); bits.Position += chk.len; bits.Align(4); } bits.Position = endSym; break; default: bits.Position = endSym; break; } } // Read the lines next. bits.Position = begin; while (bits.Position < limit) { int sig; int siz; bits.ReadInt32(out sig); bits.ReadInt32(out siz); var endSym = bits.Position + siz; switch ((DEBUG_S_SUBSECTION)sig) { case DEBUG_S_SUBSECTION.LINES: { CV_LineSection sec; bits.ReadUInt32(out sec.off); bits.ReadUInt16(out sec.sec); bits.ReadUInt16(out sec.flags); bits.ReadUInt32(out sec.cod); var func = FindFunction(funcs, sec.sec, sec.off); if (func == null) { break; } // Count the line blocks. var begSym = bits.Position; var blocks = 0; while (bits.Position < endSym) { CV_SourceFile file; bits.ReadUInt32(out file.index); bits.ReadUInt32(out file.count); bits.ReadUInt32(out file.linsiz); // Size of payload. var linsiz = (int)file.count * (8 + ((sec.flags & 1) != 0 ? 4 : 0)); bits.Position += linsiz; blocks++; } func.lines = new PdbLines[blocks]; var block = 0; bits.Position = begSym; while (bits.Position < endSym) { CV_SourceFile file; bits.ReadUInt32(out file.index); bits.ReadUInt32(out file.count); bits.ReadUInt32(out file.linsiz); // Size of payload. var src = (PdbSource)checks[(int)file.index]; var tmp = new PdbLines(src, file.count); func.lines[block++] = tmp; var lines = tmp.lines; var plin = bits.Position; var pcol = bits.Position + 8 * (int)file.count; for (var i = 0; i < file.count; i++) { CV_Line line; var column = new CV_Column(); bits.Position = plin + 8 * i; bits.ReadUInt32(out line.offset); bits.ReadUInt32(out line.flags); var lineBegin = line.flags & (uint)CV_Line_Flags.linenumStart; var delta = (line.flags & (uint)CV_Line_Flags.deltaLineEnd) >> 24; var statement = (line.flags & (uint)CV_Line_Flags.fStatement) == 0; if ((sec.flags & 1) != 0) { bits.Position = pcol + 4 * i; bits.ReadUInt16(out column.offColumnStart); bits.ReadUInt16(out column.offColumnEnd); } lines[i] = new PdbLine(line.offset, lineBegin, column.offColumnStart, lineBegin + delta, column.offColumnEnd); } } break; } } bits.Position = endSym; } }
private static Dictionary<uint, PdbTokenLine> LoadTokenToSourceMapping(Stream read) { var tokenToSourceMapping = new Dictionary<uint, PdbTokenLine>(); BitAccess bits = new BitAccess(512 * 1024); PdbFileHeader head = new PdbFileHeader(read, bits); PdbReader reader = new PdbReader(read, head.pageSize); MsfDirectory dir = new MsfDirectory(reader, head, bits); DbiModuleInfo[] modules = null; DbiDbgHdr header; dir.streams[1].Read(reader, bits); Dictionary<string, int> nameIndex = LoadNameIndex(bits); int nameStream; if (!nameIndex.TryGetValue("/NAMES", out nameStream)) { throw new Exception("No `name' stream"); } dir.streams[nameStream].Read(reader, bits); IntHashTable names = LoadNameStream(bits); dir.streams[3].Read(reader, bits); LoadDbiStream(bits, out modules, out header, true); ArrayList funcList = new ArrayList(); if (modules != null) { for (int m = 0; m < modules.Length; m++) { var module = modules[m]; if (module.stream > 0) { dir.streams[module.stream].Read(reader, bits); if (module.moduleName == "TokenSourceLineInfo") { LoadTokenToSourceInfo(bits, module, names, dir, nameIndex, reader, tokenToSourceMapping); } } } } return tokenToSourceMapping; }
public static void RunBclRewriter(string[] args) { #region Parse the command-line arguments. if (!Parser.ParseArgumentsWithUsage(args, typeof(Program))) { throw new UsageException(); } #endregion #region Figure out paths s_assemblyName = Path.GetFullPath(s_assemblyName); // this has to be specified string outputBaseName = null; if (!String.IsNullOrEmpty(s_output)) { s_output = Path.GetFullPath(s_output); outputBaseName = Path.GetFileNameWithoutExtension(s_output); } else { s_output = Path.Combine(Directory.GetCurrentDirectory(), Path.GetFileNameWithoutExtension(s_assemblyName) + ".small" + Path.GetExtension(s_assemblyName)); outputBaseName = s_assemblyName; } string pdbSourceFile = Path.ChangeExtension(s_assemblyName, "pdb"); string outputPdb = Path.ChangeExtension(s_output, "pdb"); string outputFolder = Path.GetDirectoryName(s_output); // if the user wants to do an in-place rewrite, we copy the file to a temp file if (s_output == s_assemblyName) { String tempPath = s_assemblyName + TempExtension; String tempPdbPath = pdbSourceFile + TempExtension; File.Copy(s_assemblyName, tempPath, true); s_assemblyName = tempPath; if (File.Exists(pdbSourceFile)) { File.Copy(pdbSourceFile, tempPdbPath, true); pdbSourceFile = tempPdbPath; } } if (!Directory.Exists(outputFolder)) { Directory.CreateDirectory(outputFolder); } #endregion #region Load input files HostEnvironment host = new HostEnvironment(new NameTable(), s_assemblyDependencyPaths, s_referencedAssemblies); IAssembly /*?*/ assembly = host.LoadUnitFrom(s_assemblyName) as IAssembly; // TODO: Handle multimodule assemblies if (assembly == null || assembly == Dummy.Assembly) { throw new UsageException(args[0] + " is not a PE file containing a CLR assembly, or an error occurred when loading it."); } if (!File.Exists(s_includeListFile)) { throw new UsageException(String.Format("ERROR: Can't find code model file '{0}'", s_includeListFile)); } ThinModel model = new ThinModel(new ThinnerOptions(host, new AssemblyIdentity[] { assembly.AssemblyIdentity })); model.LoadModel(s_includeListFile, new ModelReaderOptions(s_platform, s_architecture, s_flavor, s_treatFxInternalAsPublic, s_defines)); #endregion #region Calculate api closure. ConsoleTimer.StartTimer("Calculating api closure"); model.LoadMetadataFrom(assembly); ThinModel apiClosure = model.CalculateApiClosure(); if (s_keepTempFiles) { apiClosure.SaveModel(Path.ChangeExtension(s_output, ".apiClosure.xml")); } ConsoleTimer.EndTimer("Calculating api closure"); #endregion #region Calculate impl closure. ConsoleTimer.StartTimer("Calculating implementation closure"); apiClosure.LoadMetadataFrom(assembly); ThinModel implClosure = apiClosure.CalculateImplementationClosure(true, FieldOptions.KeepAll); if (s_keepTempFiles) { implClosure.SaveModel(Path.ChangeExtension(s_output, ".implClosure.xml")); } ConsoleTimer.EndTimer("Calculating implementation closure"); #endregion #region Trim. ConsoleTimer.StartTimer("Trimming assembly"); IncludeSet includeSet = new IncludeSet(); includeSet.LoadFrom(implClosure); var copier = new MetadataDeepCopier(host); Assembly copiedAssembly = copier.Copy(assembly); Trimmer trimmer = new Trimmer(includeSet, true, false, true, host, s_removeSerializable); trimmer.RewriteChildren(copiedAssembly); Assembly mutableAssembly = copiedAssembly; assembly = mutableAssembly; ConsoleTimer.EndTimer("Trimming assembly"); #endregion #region Update assembly name. ConsoleTimer.StartTimer("Updating assembly name"); // If the output assembly name is different, update the internal assembly name to match. AssemblyIdentity originalAssemblyIdentity = mutableAssembly.AssemblyIdentity; if (!outputBaseName.Equals(originalAssemblyIdentity.Name.ToString(), StringComparison.OrdinalIgnoreCase)) { mutableAssembly.Name = host.NameTable.GetNameFor(outputBaseName); mutableAssembly.ModuleName = mutableAssembly.Name; } // If we changed the assembly identity, update references to it. if (!mutableAssembly.AssemblyIdentity.Equals(originalAssemblyIdentity)) { trimmer.UpdateAssemblyReferences(originalAssemblyIdentity, mutableAssembly.AssemblyIdentity); } ConsoleTimer.EndTimer("Updating assembly name"); #endregion #region Write out the assembly ConsoleTimer.StartTimer("Writing assembly"); PdbReader pdbReader = null; PdbWriter pdbWriter = null; if (File.Exists(pdbSourceFile)) { Stream pdbStream = File.OpenRead(pdbSourceFile); pdbReader = new PdbReader(pdbStream, host); pdbWriter = new PdbWriter(outputPdb, pdbReader); Console.WriteLine("Writing pdb: {0}", outputPdb); } Console.WriteLine("Writing assembly: {0}", s_output); FileStream file = File.Create(s_output); try { PeWriter.WritePeToStream(assembly, host, file, pdbReader, pdbReader, pdbWriter); } finally { if (file != null) { file.Dispose(); } if (pdbWriter != null) { pdbWriter.Dispose(); } } ConsoleTimer.EndTimer("Writing assembly"); #endregion }
private static IntHashTable ReadSourceFileInfo( BitAccess bits, uint limit, IntHashTable names, MsfDirectory dir, Dictionary<string, int> nameIndex, PdbReader reader) { IntHashTable checks = new IntHashTable(); int begin = bits.Position; while (bits.Position < limit) { int sig; int siz; bits.ReadInt32(out sig); bits.ReadInt32(out siz); int place = bits.Position; int endSym = bits.Position + siz; switch ((DEBUG_S_SUBSECTION)sig) { case DEBUG_S_SUBSECTION.FILECHKSMS: while (bits.Position < endSym) { CV_FileCheckSum chk; int ni = bits.Position - place; bits.ReadUInt32(out chk.name); bits.ReadUInt8(out chk.len); bits.ReadUInt8(out chk.type); PdbSource src = new PdbSource(/*(uint)ni,*/ (string)names[(int)chk.name], SymDocumentType.Text, Guid.Empty, Guid.Empty); checks.Add(ni, src); bits.Position += chk.len; bits.Align(4); } bits.Position = endSym; break; default: bits.Position = endSym; break; } } return checks; }
private IUnit unit; // the module this is a lazy provider for #endregion Fields #region Constructors /// <summary> /// Allocates an object that can be used to query for contracts by asking questions about specific methods/types, etc. /// </summary> /// <param name="host">The host that loaded the unit for which this is to be a contract provider.</param> /// <param name="unit">The unit to retrieve the contracts from.</param> /// <param name="contractMethods">A collection of methods that can be called in a way that provides tools with information about contracts.</param> /// <param name="usePdb">Whether to use the PDB file (and possibly the source files if available) during extraction.</param> public LazyContractExtractor(IContractAwareHost host, IUnit unit, IContractMethods contractMethods, bool usePdb) { this.host = host; this.underlyingContractProvider = new ContractProvider(contractMethods, unit); if (usePdb) { string pdbFile = Path.ChangeExtension(unit.Location, "pdb"); if (File.Exists(pdbFile)) { using (var pdbStream = File.OpenRead(pdbFile)) { this.pdbReader = new PdbReader(pdbStream, host); } } } this.unit = unit; }
/// <summary> /// Returns a mutable Code Model module that is equivalent to the given Metadata Model module, /// except that in the new module method bodies also implement ISourceMethodBody. /// </summary> /// <param name="host">An object representing the application that is hosting this decompiler. It is used to obtain access to some global /// objects and services such as the shared name table and the table for interning references.</param> /// <param name="module">The root of the Metadata Model to be converted to a Code Model.</param> /// <param name="pdbReader">An object that can map offsets in an IL stream to source locations and block scopes. May be null.</param> /// <param name="options">Set of options that control decompilation.</param> public static Module GetCodeModelFromMetadataModel(IMetadataHost host, IModule module, PdbReader/*?*/ pdbReader, DecompilerOptions options = DecompilerOptions.None) { return GetCodeModelFromMetadataModelHelper(host, module, pdbReader, pdbReader, options); }
/// <summary> /// Returns a mutable Code Model module that is equivalent to the given Metadata Model module, /// except that in the new module method bodies also implement ISourceMethodBody. /// </summary> /// <param name="host">An object representing the application that is hosting this decompiler. It is used to obtain access to some global /// objects and services such as the shared name table and the table for interning references.</param> /// <param name="module">The root of the Metadata Model to be converted to a Code Model.</param> /// <param name="pdbReader">An object that can map offsets in an IL stream to source locations and block scopes. May be null.</param> /// <param name="options">Set of options that control decompilation.</param> public static Module GetCodeModelFromMetadataModel(IMetadataHost host, IModule module, PdbReader /*?*/ pdbReader, DecompilerOptions options = DecompilerOptions.None) { return(GetCodeModelFromMetadataModelHelper(host, module, pdbReader, pdbReader, options)); }
public virtual StatementTraverser MakeStatementTraverser(Sink sink, PdbReader /*?*/ pdbReader, bool contractContext) { return(new StatementTraverser(sink, pdbReader, contractContext, this)); }
public List <TestAssembly> FindTestsInProjects(List <ProjectDirectoryWrapper> assemblies) { List <TestWrapper> tests = new List <TestWrapper>(); using (var host = new PeReader.DefaultHost()) { foreach (var pathWrapper in assemblies) { if (pathWrapper != null && !string.IsNullOrEmpty(pathWrapper.OutputDirectory)) { var module = host.LoadUnitFrom(pathWrapper.OutputDirectory.Replace(" ", "#")) as IModule; foreach (var type in module.GetAllTypes()) { foreach (var method in type.Methods) { if (method.Attributes.Any(attribute => attribute.Type.ToString() == typeof(TestAttribute).ToString() || attribute.Type.ToString() == typeof(TestMethodAttribute).ToString())) { foreach (var location in method.Locations) { PdbReader pdbReader = null; string pdbFile = Path.ChangeExtension(module.Location, "pdb"); if (File.Exists(pdbFile)) { Stream pdbStream = File.OpenRead(pdbFile); pdbReader = new PdbReader(pdbStream, host); using (pdbReader) { var sourceLocations = pdbReader.GetPrimarySourceLocationsFor(location); foreach (var sourceLocation in sourceLocations) { tests.Add(new TestWrapper() { AssemblyPath = module.Location, AssemblyName = module.Name.Value, ClassName = type.Name.Value, ClassNamespace = type.ToString().Substring(0, type.ToString().Length - type.Name.Value.Length - 1), LineNumber = sourceLocation.StartLine, Filename = sourceLocation.SourceDocument.Location, MethodName = method.Name.Value }); // Yay!! } } } else { // Just add the class, no line numbers } } } } } } } } return(ExtractAssembliesFromWrapper(tests)); }
internal void Read(PdbReader reader, BitAccess bits) { bits.MinCapacity(contentSize); Read(reader, 0, bits.Buffer, 0, contentSize); }
public void Dispose() { PdbReader.Dispose(); }
public ILMutator(IMetadataHost host, PdbReader pdbReader) : base(host, true) { this.pdbReader = pdbReader; }
private static void LoadTokenToSourceInfo( BitAccess bits, DbiModuleInfo module, IntHashTable names, MsfDirectory dir, Dictionary<string, int> nameIndex, PdbReader reader, Dictionary<uint, PdbTokenLine> tokenToSourceMapping) { bits.Position = 0; int sig; bits.ReadInt32(out sig); if (sig != 4) { throw new Exception(string.Format("Invalid signature. (sig={0})", sig)); } bits.Position = 4; while (bits.Position < module.cbSyms) { ushort siz; ushort rec; bits.ReadUInt16(out siz); int star = bits.Position; int stop = bits.Position + siz; bits.Position = star; bits.ReadUInt16(out rec); switch ((SYM)rec) { case SYM.S_OEM: OemSymbol oem; bits.ReadGuid(out oem.idOem); bits.ReadUInt32(out oem.typind); // internal byte[] rgl; // user data, force 4-byte alignment if (oem.idOem == MsilMetaData) { string name = bits.ReadString(); if (name == "TSLI") { uint token; uint file_id; uint line; uint column; uint endLine; uint endColumn; bits.ReadUInt32(out token); bits.ReadUInt32(out file_id); bits.ReadUInt32(out line); bits.ReadUInt32(out column); bits.ReadUInt32(out endLine); bits.ReadUInt32(out endColumn); PdbTokenLine tokenLine; if (!tokenToSourceMapping.TryGetValue(token, out tokenLine)) tokenToSourceMapping.Add(token, new PdbTokenLine(token, file_id, line, column, endLine, endColumn)); else { while (tokenLine.nextLine != null) tokenLine = tokenLine.nextLine; tokenLine.nextLine = new PdbTokenLine(token, file_id, line, column, endLine, endColumn); } } bits.Position = stop; break; } else { throw new Exception(string.Format("OEM section: guid={0} ti={1}", oem.idOem, oem.typind)); } case SYM.S_END: bits.Position = stop; break; default: bits.Position = stop; break; } } bits.Position = module.cbSyms + module.cbOldLines; int limit = module.cbSyms + module.cbOldLines + module.cbLines; IntHashTable sourceFiles = ReadSourceFileInfo(bits, (uint)limit, names, dir, nameIndex, reader); foreach (var tokenLine in tokenToSourceMapping.Values) { tokenLine.sourceFile = (PdbSource)sourceFiles[(int)tokenLine.file_id]; } }
// TODO: First search the moveNextBody to see if there are any contracts at all. /// <summary> /// /// </summary> /// <param name="host"></param> /// <param name="extractor"></param> /// <param name="iteratorMethodBody"></param> /// <param name="moveNextBody"></param> /// <param name="pdbReader"></param> /// <returns></returns> public static MethodContract GetMethodContractFromMoveNext( IContractAwareHost host, ContractExtractor extractor, ISourceMethodBody iteratorMethodBody, ISourceMethodBody moveNextBody, PdbReader pdbReader ) { // Walk the iterator method and collect all of the state that is assigned to fields in the iterator class // That state needs to replace any occurrences of the fields in the contracts (if they exist...) var iteratorStmts = new List <IStatement>(iteratorMethodBody.Block.Statements); Dictionary <uint, IExpression> capturedThings = new Dictionary <uint, IExpression>(); // Find all of the state captured for the IEnumerable // REVIEW: Is this state ever used in the contracts? Since they're all sitting in the MoveNext // method, maybe they always use the IEnumerator state? if (1 < iteratorStmts.Count) { // First statement should be the creation of the iterator class int j = 1; while (j < iteratorStmts.Count) { var es = iteratorStmts[j++] as IExpressionStatement; if (es == null) { break; } var assign = es.Expression as IAssignment; if (assign == null) { break; } var field = assign.Target.Definition as IFieldReference; var capturedThing = assign.Source; var k = field.InternedKey; var spec = field as ISpecializedFieldReference; if (spec != null) { k = spec.UnspecializedVersion.InternedKey; } capturedThings.Add(k, capturedThing); } } else { var ret = iteratorStmts[0] as IReturnStatement; if (ret != null) { var be = ret.Expression as IBlockExpression; if (be != null) { var beStmts = new List <IStatement>(be.BlockStatement.Statements); var j = 1; while (j < beStmts.Count) { var es = beStmts[j++] as IExpressionStatement; if (es == null) { break; } var assign = es.Expression as IAssignment; if (assign == null) { break; } var field = assign.Target.Definition as IFieldReference; var capturedThing = assign.Source; var k = field.InternedKey; var spec = field as ISpecializedFieldReference; if (spec != null) { k = spec.UnspecializedVersion.InternedKey; } capturedThings.Add(k, capturedThing); } } } } // Find all of the state captured for the IEnumerator // That state is captured at the beginning of the IEnumerable<T>.GetEnumerator method IMethodDefinition getEnumerator = null; var t = moveNextBody.MethodDefinition.ContainingTypeDefinition; foreach (IMethodImplementation methodImplementation in t.ExplicitImplementationOverrides) { if (methodImplementation.ImplementedMethod.Name == host.NameTable.GetNameFor("GetEnumerator")) { var gtir = methodImplementation.ImplementedMethod.ContainingType as IGenericTypeInstanceReference; if (gtir != null && TypeHelper.TypesAreEquivalent(gtir.GenericType, host.PlatformType.SystemCollectionsGenericIEnumerable)) { getEnumerator = methodImplementation.ImplementingMethod.ResolvedMethod as IMethodDefinition; break; } } } if (getEnumerator != null) { IMethodBody geBody = getEnumerator.Body; var sourceGeBody = geBody as ISourceMethodBody; if (sourceGeBody == null) { sourceGeBody = Decompiler.GetCodeModelFromMetadataModel(host, geBody, pdbReader, DecompilerOptions.AnonymousDelegates); } foreach (var stmt in sourceGeBody.Block.Statements) { var es = stmt as IExpressionStatement; if (es == null) { continue; } var assign = es.Expression as IAssignment; if (assign == null) { continue; } var field2 = assign.Target.Definition as IFieldReference; if (field2 == null) { continue; } var k = field2.InternedKey; var spec = field2 as ISpecializedFieldReference; if (spec != null) { k = spec.UnspecializedVersion.InternedKey; } var sourceBe = assign.Source as IBoundExpression; if (sourceBe == null) { continue; } var field3 = sourceBe.Definition as IFieldReference; if (field3 == null) { continue; } var k3 = field3.InternedKey; var spec3 = field3 as ISpecializedFieldReference; if (spec3 != null) { k3 = spec3.UnspecializedVersion.InternedKey; } IExpression capturedThing = null; if (!capturedThings.TryGetValue(k3, out capturedThing)) { continue; } capturedThings[k] = capturedThing; } } var mc = HermansAlwaysRight.ExtractContracts(host, pdbReader, extractor, moveNextBody); if (mc == null) { return(mc); } // substitute all field references in contract with the captured state var replacer = new Replacer(host, capturedThings, iteratorMethodBody.MethodDefinition, moveNextBody.MethodDefinition); replacer.RewriteChildren(mc); if (moveNextBody.MethodDefinition.ContainingTypeDefinition.IsGeneric) { var genericParameterMapper = new GenericMethodParameterMapper(host, iteratorMethodBody.MethodDefinition, moveNextBody.MethodDefinition.ContainingType as INestedTypeReference); mc = genericParameterMapper.Rewrite(mc) as MethodContract; } return(mc); }
/// <summary> /// Returns a mutable Code Model assembly that is equivalent to the given Metadata Model assembly, /// except that in the new assembly method bodies also implement ISourceMethodBody. /// </summary> /// <param name="host">An object representing the application that is hosting this decompiler. It is used to obtain access to some global /// objects and services such as the shared name table and the table for interning references.</param> /// <param name="assembly">The root of the Metadata Model to be converted to a Code Model.</param> /// <param name="pdbReader">An object that can map offsets in an IL stream to source locations and block scopes. May be null.</param> /// <param name="options">Set of options that control decompilation.</param> public static Assembly GetCodeModelFromMetadataModel(IMetadataHost host, IAssembly assembly, PdbReader/*?*/ pdbReader, DecompilerOptions options = DecompilerOptions.None) { return (Assembly)GetCodeModelFromMetadataModelHelper(host, assembly, pdbReader, pdbReader, options); }
private HermansAlwaysRight(IContractAwareHost contractAwareHost, ContractExtractor extractor, ISourceMethodBody sourceMethodBody, bool methodIsInReferenceAssembly, OldAndResultExtractor oldAndResultExtractor, PdbReader /*?*/ pdbReader) : base(contractAwareHost) { this.contractAwareHost = contractAwareHost; this.extractor = extractor; this.sourceMethodBody = sourceMethodBody; this.methodIsInReferenceAssembly = methodIsInReferenceAssembly; this.oldAndResultExtractor = oldAndResultExtractor; this.pdbReader = pdbReader; }
/// <summary> /// Returns a (mutable) Code Model SourceMethod body that is equivalent to the given Metadata Model method body. /// It does *not* delete any helper types. /// </summary> /// <param name="host">An object representing the application that is hosting this decompiler. It is used to obtain access to some global /// objects and services such as the shared name table and the table for interning references.</param> /// <param name="methodBody">The Metadata Model method body that is to be decompiled.</param> /// <param name="pdbReader">An object that can map offsets in an IL stream to source locations and block scopes. May be null.</param> /// <param name="options">Set of options that control decompilation.</param> public static ISourceMethodBody GetCodeModelFromMetadataModel(IMetadataHost host, IMethodBody methodBody, PdbReader/*?*/ pdbReader, DecompilerOptions options = DecompilerOptions.None) { return new Microsoft.Cci.ILToCodeModel.SourceMethodBody(methodBody, host, pdbReader, pdbReader, options); }
public static MethodContract /*?*/ ExtractContracts(IContractAwareHost contractAwareHost, PdbReader /*?*/ pdbReader, ContractExtractor extractor, ISourceMethodBody methodBody) { var definingUnit = TypeHelper.GetDefiningUnit(methodBody.MethodDefinition.ContainingType.ResolvedType); var methodIsInReferenceAssembly = ContractHelper.IsContractReferenceAssembly(contractAwareHost, definingUnit); var oldAndResultExtractor = new OldAndResultExtractor(contractAwareHost, methodBody, extractor.IsContractMethod); var localsInitializedWithFields = FindLocals.FindSetOfLocals(methodBody); var har = new HermansAlwaysRight(contractAwareHost, extractor, methodBody, methodIsInReferenceAssembly, oldAndResultExtractor, pdbReader); har.Rewrite(methodBody); if (har.extractor.currentMethodContract == null) { return(null); } // The decompiler will have introduced locals if there were any anonymous delegates in the contracts // Such locals are initialized with the fields of the iterator class. // The contract that comes back from here will have those fields replaced with whatever the iterator captured // (parameters, locals). So the locals in the contract need to be replaced with the iterator fields so that // next replacement will see the right thing (i.e., the fields) and replace them! Phew! var localReplacer = new LocalReplacer(contractAwareHost, localsInitializedWithFields); localReplacer.Rewrite(har.extractor.currentMethodContract); // also need to rewrite the remainder of the body localReplacer.Rewrite(methodBody); return(har.extractor.currentMethodContract); }
/// <summary> /// </summary> /// <param name="reader"> /// </param> /// <param name="bits"> /// </param> internal void Read(PdbReader reader, BitAccess bits) { bits.MinCapacity(this.contentSize); this.Read(reader, 0, bits.Buffer, 0, this.contentSize); }
public static SourceCodeLocation OfType(this INamedTypeDefinition type, PdbReader pdb) { return(SourceCodeLocation.None); }
/// <summary> /// Allocates a metadata (IL) representation along with a source level representation of the body of a method or of a property/event accessor. /// </summary> /// <param name="ilMethodBody">A method body whose IL operations should be decompiled into a block of statements that will be the /// result of the Block property of the resulting source method body.</param> /// <param name="host">An object representing the application that is hosting the converter. It is used to obtain access to some global /// objects and services such as the shared name table and the table for interning references.</param> /// <param name="sourceLocationProvider">An object that can map some kinds of ILocation objects to IPrimarySourceLocation objects. May be null.</param> /// <param name="localScopeProvider">An object that can provide information about the local scopes of a method.</param> /// <param name="options">Set of options that control decompilation.</param> public SourceMethodBody(IMethodBody ilMethodBody, IMetadataHost host, ISourceLocationProvider/*?*/ sourceLocationProvider, ILocalScopeProvider/*?*/ localScopeProvider, DecompilerOptions options = DecompilerOptions.None) : base(host, sourceLocationProvider) { this.ilMethodBody = ilMethodBody; this.host = host; this.nameTable = host.NameTable; this.sourceLocationProvider = sourceLocationProvider; this.pdbReader = sourceLocationProvider as PdbReader; this.localScopeProvider = localScopeProvider; this.options = options; this.platformType = ilMethodBody.MethodDefinition.ContainingTypeDefinition.PlatformType; this.operationEnumerator = ilMethodBody.Operations.GetEnumerator(); if (IteratorHelper.EnumerableIsNotEmpty(ilMethodBody.LocalVariables)) this.LocalsAreZeroed = ilMethodBody.LocalsAreZeroed; else this.LocalsAreZeroed = true; this.MethodDefinition = ilMethodBody.MethodDefinition; }
private static SourceCodeLocation Of(this IObjectWithLocations locatable, PdbReader pdb) { IPrimarySourceLocation location = locatable.GetValidLocation(pdb); return(location != null?location.ToSourceCodeLocation() : SourceCodeLocation.None); }