public virtual ILGenerator MinimalReplacementGeneratorForBody(IMethodBody methodBody) {
      var generator = new ILGenerator(host, methodBody.MethodDefinition);

      AppendEmitExceptionThrow(generator);

      return generator;
    }
 public SynthesizedMethodBodyDecorator(IMethodBody methodBody, IList<IType> locals, byte[] customBody)
     : this(methodBody)
 {
     this.customBody = customBody;
     var index = 0;
     this.locals = locals.Select(t => new SynthesizedLocalVariable(index++, t)).ToList();
 }
示例#3
0
    public override void Traverse(IMethodBody methodBody) {
      sourceEmitterOutput.WriteLine("");
      this.sourceEmitterOutput.WriteLine(MemberHelper.GetMethodSignature(methodBody.MethodDefinition,
        NameFormattingOptions.Signature|NameFormattingOptions.ReturnType|NameFormattingOptions.ParameterModifiers|NameFormattingOptions.ParameterName));
      sourceEmitterOutput.WriteLine("");
      if (this.pdbReader != null)
        PrintScopes(methodBody);
      else
        PrintLocals(methodBody.LocalVariables);

      this.cdfg = ControlAndDataFlowGraph<AiBasicBlock<Instruction>, Instruction>.GetControlAndDataFlowGraphFor(host, methodBody, this.pdbReader);
      this.cfgQueries = new ControlGraphQueries<AiBasicBlock<Instruction>, Instruction>(this.cdfg);
      SingleAssigner<AiBasicBlock<Instruction>, Instruction>.GetInSingleAssignmentForm(host.NameTable, this.cdfg, this.cfgQueries, this.pdbReader);
      this.valueMappings = new ValueMappings<Instruction>(this.host.PlatformType, new Z3Wrapper.Wrapper(host.PlatformType));
      AbstractInterpreter<AiBasicBlock<Instruction>, Instruction>.InterpretUsingAbstractValues(this.cdfg, this.cfgQueries, this.valueMappings);

      var numberOfBlocks = this.cdfg.BlockFor.Count;

      foreach (var block in this.cdfg.AllBlocks) {
        this.PrintBlock(block);
      }

      sourceEmitterOutput.WriteLine("**************************************************************");
      sourceEmitterOutput.WriteLine();
    }
    internal InstructionParser(SourceMethodBody sourceMethodBody) {
      Contract.Requires(sourceMethodBody != null);

      this.sourceMethodBody = sourceMethodBody;
      this.host = sourceMethodBody.host; Contract.Assume(this.host != null);
      this.ilMethodBody = sourceMethodBody.ilMethodBody; Contract.Assume(this.ilMethodBody != null);
      this.MethodDefinition = sourceMethodBody.MethodDefinition;
      this.nameTable = sourceMethodBody.nameTable; Contract.Assume(this.nameTable != null);
      this.sourceLocationProvider = sourceMethodBody.sourceLocationProvider;
      this.localScopeProvider = sourceMethodBody.localScopeProvider;
      this.options = sourceMethodBody.options;
      this.platformType = sourceMethodBody.platformType; Contract.Assume(this.platformType != null);
      this.numberOfAssignmentsToLocal = sourceMethodBody.numberOfAssignmentsToLocal; Contract.Assume(this.numberOfAssignmentsToLocal != null);
      this.numberOfReferencesToLocal = sourceMethodBody.numberOfReferencesToLocal; Contract.Assume(this.numberOfReferencesToLocal != null);
      this.gotosThatTarget = sourceMethodBody.gotosThatTarget; Contract.Assume(this.gotosThatTarget != null);
      this.cdfg = sourceMethodBody.cdfg; Contract.Assume(this.cdfg != null);
      this.bindingsThatMakeALastUseOfALocalVersion = sourceMethodBody.bindingsThatMakeALastUseOfALocalVersion; Contract.Assume(this.bindingsThatMakeALastUseOfALocalVersion != null);

      if (this.localScopeProvider != null) {
        var syncInfo = this.localScopeProvider.GetSynchronizationInformation(sourceMethodBody);
        if (syncInfo != null) {
          var syncPointFor = this.synchronizatonPointLocationFor = new Hashtable<SynchronizationPointLocation>();
          IDocument doc = Dummy.Document;
          foreach (var loc in this.MethodDefinition.Locations) { doc = loc.Document; break; }
          foreach (var syncPoint in syncInfo.SynchronizationPoints) {
            Contract.Assume(syncPoint != null);
            var syncLoc = new SynchronizationPointLocation(doc, syncPoint);
            syncPointFor[syncPoint.SynchronizeOffset] = syncLoc;
            if (syncPoint.ContinuationMethod == null)
              syncPointFor[syncPoint.ContinuationOffset] = syncLoc;
          }
        }
      }
    }
    public override ILGenerator DebugReplacementGeneratorForBody(IMethodBody methodBody) {
      string warningText = "Attempt to execute garbage collected method: " + methodBody.MethodDefinition.ToString();

      var generator = new ILGenerator(host, methodBody.MethodDefinition);

      // emit console warning
      generator.Emit(OperationCode.Ldstr, warningText);
      generator.Emit(OperationCode.Call, this.consoleWriteLine);

      //emit stack trace

      // pushes stack trace on stack
      generator.Emit(OperationCode.Call, this.environmentGetStackTrace);
      // consumes stack trace
      generator.Emit(OperationCode.Call, this.consoleWriteLine);

      // may want to flush output?

      // emit exit

      generator.Emit(OperationCode.Ldc_I4_M1);
      generator.Emit(OperationCode.Call, this.environmentExit);

      // Makes the verifier happy; this should never be reached

      AppendEmitExceptionThrow(generator);

      return generator;
    }
        /// <summary>
        /// </summary>
        /// <param name="type">
        /// </param>
        /// <param name="typeResolver">
        /// </param>
        public SynthesizedSingleDimArrayIListSetItemMethod(IType arrayType, ITypeResolver typeResolver)
            : base("set_Item", arrayType, typeResolver.System.System_Void)
        {
            var codeList = new IlCodeBuilder();
            codeList.LoadArgument(0);
            codeList.LoadArgument(1);
            codeList.LoadArgument(2);
            codeList.Add(Code.Stelem, 1);
            codeList.Add(Code.Ret);

            var locals = new List<IType>();

            this._methodBody =
                new SynthesizedMethodBodyDecorator(
                    null,
                    locals,
                    codeList.GetCode());

            this._parameters = new List<IParameter>();
            this._parameters.Add(typeResolver.System.System_Int32.ToParameter());
            this._parameters.Add(arrayType.GetElementType().ToParameter());

            this._tokenResolutions = new List<object>();
            this._tokenResolutions.Add(arrayType.GetElementType());
        }
        /// <summary>
        /// </summary>
        /// <param name="type">
        /// </param>
        /// <param name="typeResolver">
        /// </param>
        public SynthesizedSingleDimArrayIListGetEnumeratorMethod(IType arrayType, ITypeResolver typeResolver)
            : base("GetEnumerator", arrayType, typeResolver.System.System_Collections_Generic_IEnumerator_T.Construct(arrayType.GetElementType()))
        {
            var codeList = new IlCodeBuilder();
            codeList.LoadArgument(0);
            codeList.Add(Code.Newobj, 1);
            codeList.Add(Code.Newobj, 2);
            codeList.Add(Code.Ret);

            var locals = new List<IType>();

            this._methodBody =
                new SynthesizedMethodBodyDecorator(
                    null,
                    locals,
                    codeList.GetCode());

            this._parameters = new List<IParameter>();

            this._tokenResolutions = new List<object>();

            var arraySegmentType = typeResolver.System.System_ArraySegment_T1.Construct(arrayType.GetElementType());
            this._tokenResolutions.Add(
                IlReader.Constructors(arraySegmentType, typeResolver).First(c => c.GetParameters().Count() == 1));
            this._tokenResolutions.Add(
                IlReader.Constructors(arraySegmentType.GetNestedTypes().First(), typeResolver).First(c => c.GetParameters().Count() == 1));
        }
 protected void VerifyResult(IMethodBody mb)
 {
     var s_actual = mb.StringJoin(Environment.NewLine);
     s_actual = Regex.Replace(s_actual, @"Snippets.<>c__DisplayClass.*::", "<Closure>::");
     s_actual = Regex.Replace(s_actual, @"CS\$<>8__locals.*\)", "<Closure>)");
     s_actual = Regex.Replace(s_actual, @"0x[a-fA-f0-9]{8}", "<MetadataToken>");
     VerifyResult(s_actual);
 }
        /// <summary>
        /// Rewrites the target method body. This class will only insert a single call into the beginning of the
        /// method that writes it's signature using the <see cref="TestUtil"/> class.
        /// </summary>
        /// <param name="methodBody">
        /// The method body to rewrite.
        /// </param>
        /// <returns>
        /// The rewritten method body.
        /// </returns>
        public override IMethodBody Rewrite(IMethodBody methodBody)
        {
            if (this.rewriter == null)
            {
                throw new InvalidOperationException("Unable to rewrite method body. Call Rewrite(IInstrumentationTarget target) instead of calling this directly.");
            }

            return this.rewriter.Rewrite(methodBody);
        }
示例#10
0
        public byte[] SerializeMethodDebugInfo(EmitContext context, IMethodBody methodBody, uint methodToken, bool isEncDelta, bool suppressNewCustomDebugInfo, out bool emitExternNamespaces)
        {
            emitExternNamespaces = false;

            // CONSIDER: this may not be the same "first" method as in Dev10, but
            // it shouldn't matter since all methods will still forward to a method
            // containing the appropriate information.
            if (_methodBodyWithModuleInfo == null) //UNDONE: || edit-and-continue
            {
                // This module level information could go on every method (and does in
                // the edit-and-continue case), but - as an optimization - we'll just
                // put it on the first method we happen to encounter and then put a
                // reference to the first method's token in every other method (so they
                // can find the information).
                if (context.Module.GetAssemblyReferenceAliases(context).Any())
                {
                    _methodTokenWithModuleInfo = methodToken;
                    _methodBodyWithModuleInfo = methodBody;
                    emitExternNamespaces = true;
                }
            }

            var customDebugInfo = ArrayBuilder<MemoryStream>.GetInstance();

            SerializeIteratorClassMetadata(methodBody, customDebugInfo);

            // NOTE: This is an attempt to match Dev10's apparent behavior.  For iterator methods (i.e. the method
            // that appears in source, not the synthesized ones), Dev10 only emits the ForwardIterator and IteratorLocal
            // custom debug info (e.g. there will be no information about the usings that were in scope).
            // NOTE: There seems to be an unusual behavior in ISymUnmanagedWriter where, if all the methods in a type are
            // iterator methods, no custom debug info is emitted for any method.  Adding a single non-iterator
            // method causes the custom debug info to be produced for all methods (including the iterator methods).
            // Since we are making the same ISymUnmanagedWriter calls as Dev10, we see the same behavior (i.e. this
            // is not a regression).
            if (methodBody.StateMachineTypeName == null)
            {
                SerializeNamespaceScopeMetadata(context, methodBody, customDebugInfo);
                SerializeStateMachineLocalScopes(methodBody, customDebugInfo);
            }

            if (!suppressNewCustomDebugInfo)
            {
                SerializeDynamicLocalInfo(methodBody, customDebugInfo);

                // delta doesn't need this information - we use information recorded by previous generation emit
                if (!isEncDelta)
                {
                    var encMethodInfo = MetadataWriter.GetEncMethodDebugInfo(methodBody);
                    SerializeCustomDebugInformation(encMethodInfo, customDebugInfo);
                }
            }

            byte[] result = SerializeCustomDebugMetadata(customDebugInfo);
            customDebugInfo.Free();
            return result;
        }
 public SynthesizedMethodDecorator(
     IMethod method,
     IMethodBody methodBody,
     IEnumerable<IParameter> parameters,
     IModule module) : this(method)
 {
     this.methodBody = methodBody;
     this.module = module;
     this.parameters = parameters;
 }
    public override IMethodBody Rewrite(IMethodBody methodBody) {
      this.cdfg = ControlAndDataFlowGraph<BasicBlock<Instruction>, Instruction>.GetControlAndDataFlowGraphFor(this.host, methodBody);
      this.ilGenerator = new ILGenerator(host, methodBody.MethodDefinition);

      var numberOfBlocks = this.cdfg.BlockFor.Count;
      this.labelFor = new Hashtable<ILGeneratorLabel>(numberOfBlocks);
      this.counterFieldsForCurrentMethod = new NestedTypeDefinition() {
        BaseClasses = new List<ITypeReference>(1) { this.host.PlatformType.SystemObject },
        ContainingTypeDefinition = methodBody.MethodDefinition.ContainingTypeDefinition,
        Fields = new List<IFieldDefinition>((int)numberOfBlocks*2),
        Methods = new List<IMethodDefinition>(1),
        InternFactory = this.host.InternFactory,
        IsBeforeFieldInit = true,
        IsClass = true,
        IsSealed = true,
        IsAbstract = true,
        Name = this.host.NameTable.GetNameFor(methodBody.MethodDefinition.Name+"_Counters"+methodBody.MethodDefinition.InternedKey),
        Visibility = TypeMemberVisibility.Assembly,
      };
      this.fieldOffsets = new List<uint>((int)numberOfBlocks*2);

      foreach (var exceptionInfo in methodBody.OperationExceptionInformation) {
        this.ilGenerator.AddExceptionHandlerInformation(exceptionInfo.HandlerKind, exceptionInfo.ExceptionType,
          this.GetLabelFor(exceptionInfo.TryStartOffset), this.GetLabelFor(exceptionInfo.TryEndOffset),
          this.GetLabelFor(exceptionInfo.HandlerStartOffset), this.GetLabelFor(exceptionInfo.HandlerEndOffset),
          exceptionInfo.HandlerKind == HandlerKind.Filter ? this.GetLabelFor(exceptionInfo.FilterDecisionStartOffset) : null);
      }

      if (this.pdbReader == null) {
        foreach (var localDef in methodBody.LocalVariables)
          this.ilGenerator.AddVariableToCurrentScope(localDef);
      } else {
        foreach (var ns in this.pdbReader.GetNamespaceScopes(methodBody)) {
          foreach (var uns in ns.UsedNamespaces)
            this.ilGenerator.UseNamespace(uns.NamespaceName.Value);
        }
        this.scopeEnumerator = this.pdbReader.GetLocalScopes(methodBody).GetEnumerator();
        this.scopeEnumeratorIsValid = this.scopeEnumerator.MoveNext();
      }

      foreach (var block in this.cdfg.AllBlocks)
        this.InstrumentBlock(block);

      while (this.scopeStack.Count > 0) {
        this.ilGenerator.EndScope();
        this.scopeStack.Pop();
      }

      this.ilGenerator.AdjustBranchSizesToBestFit();

      this.InjectMethodToDumpCounters();

      return new ILGeneratorMethodBody(this.ilGenerator, methodBody.LocalsAreZeroed, (ushort)(methodBody.MaxStack+2), methodBody.MethodDefinition,
        methodBody.LocalVariables, IteratorHelper.GetSingletonEnumerable((ITypeDefinition)this.counterFieldsForCurrentMethod));
    }
        public static ControlFlowGraph DoBuildControlFlowGraph(IMethodBody cil, Symbols symbols)
        {
            ReadOnlyDictionary<ControlFlowBlock, ReadOnlyCollection<IILOp>> blocks2parts;
            var cfg = CreateCarcass.DoCreateCarcass(cil, out blocks2parts);
            foreach (var cfb in blocks2parts.Keys)
            {
                InitialDecompilation.DoPrimaryDecompilation(cfb, blocks2parts[cfb], symbols);
            }

            return cfg;
        }
        internal void SerializeMethodDynamicAnalysisData(IMethodBody bodyOpt)
        {
            var data = bodyOpt?.DynamicAnalysisData;

            if (data == null)
            {
                _methodTable.Add(default(MethodRow));
                return;
            }

            BlobHandle spanBlob = SerializeSpans(data.Spans, _documentIndex);
            _methodTable.Add(new MethodRow { Spans = spanBlob });
        }
            public override IMethodBody Rewrite(IMethodBody body)
            {
                var method = body.MethodDefinition;
                _log.Info("Rewriting IMethodBody of: " + method + " Pass: " + MutationTarget.PassInfo);
     
                var newBody = new SourceMethodBody(Host)
                {
                    MethodDefinition = method,
                    LocalsAreZeroed = true
                };
                var block = new BlockStatement();
                newBody.Block = block;

                var replacement = method.ContainingTypeDefinition.Methods.Single(m => m.ToString() == MutationTarget.PassInfo);
                var methodCall = new MethodCall
                    {
                        MethodToCall = replacement,
                        Type = replacement.Type,
                        ThisArgument = new ThisReference() {Type = method.ContainingTypeDefinition}
                    };
                foreach (var param in replacement.Parameters)
                {
                    methodCall.Arguments.Add(new BoundExpression()
                        {
                            Definition = method.Parameters
                                .First(p =>
                                    ((INamedTypeReference)p.Type).Name.Value ==
                                    ((INamedTypeReference)param.Type).Name.Value)
                        });
                    //  methodCall.Arguments.Add(method.Parameters.First(p => new ));
                }

                if (replacement.Type == Host.PlatformType.SystemVoid)
                {
                    block.Statements.Add(new ExpressionStatement
                    {
                        Expression = methodCall
                    });
                    block.Statements.Add(new ReturnStatement());
                }
                else
                {
                    block.Statements.Add(new ReturnStatement
                    {
                        Expression = methodCall
                    });
                   
                }
        
                return newBody;
            }
            public override void Visit(IMethodBody body)
            {
                var method = body.MethodDefinition;
                _log.Info("Visiting IMethodBody of: " + method);

                var methods = FindCandidateMethods(method);
                var compatibileMethods = methods.Where(m => m.Parameters
                    .All(p => method.Parameters.Any(p2 => p2.Type == p.Type))).ToList();

                if(compatibileMethods.Count != 0)
                {
              
                    MarkMutationTarget(body, compatibileMethods.First().ToString().InList());
                }
  
            }
        /// <summary>
        /// </summary>
        /// <param name="type">
        /// </param>
        /// <param name="typeResolver">
        /// </param>
        public SynthesizedCtorSBytePtrStartLengthMethod(ITypeResolver typeResolver)
            : base("CtorSBytePtrStartLengthEncoding", typeResolver.System.System_String, typeResolver.System.System_String)
        {
            byte[] code;
            IList<object> tokenResolutions;
            IList<IType> locals;
            IList<IParameter> parameters;
            StringGen.GetCtorSBytePtrStartLength(typeResolver, out code, out tokenResolutions, out locals, out parameters);

            this._methodBody = new SynthesizedMethodBodyDecorator(
                null,
                locals,
                code);

            this._parameters = parameters;
            this._tokenResolutions = tokenResolutions;
        }
        /// <summary>
        /// </summary>
        /// <param name="type">
        /// </param>
        /// <param name="typeResolver">
        /// </param>
        public SynthesizedStrLenMethod(ITypeResolver typeResolver)
            : base("strlen", typeResolver.System.System_String, typeResolver.System.System_Int32)
        {
            byte[] code;
            IList<object> tokenResolutions;
            IList<IType> locals;
            IList<IParameter> parameters;
            StringGen.GetStrLen(typeResolver, out code, out tokenResolutions, out locals, out parameters);

            this._methodBody = new SynthesizedMethodBodyDecorator(
                null,
                locals,
                code);

            this._parameters = parameters;
            this._tokenResolutions = tokenResolutions;
        }
        public override void Traverse(IMethodBody methodBody)
        {
            var moduleInfo =  _module.ModulesInfo.Single();
            var smb =  new Microsoft.Cci.ILToCodeModel.SourceMethodBody(methodBody, _module.Host, moduleInfo.PdbReader, moduleInfo.LocalScopeProvider, DecompilerOptions.None);
           
            _visitor.MethodBodyEnter(smb);
            Traverse(smb);
            var descriptor = _visitor.MethodBodyExit(smb);
            var targetsDescriptors = _visitor.MutationTargets.Select(t => t.ProcessingContext.Descriptor).ToList();

          //  _log.Debug("Returned :"+ descriptor+" comparing with mutaion targets: "+ targetsDescriptors.MakeString());
            if(targetsDescriptors.Any(a => a.IsContainedIn(descriptor)))
            {
                _log.Debug("Adding method body :" + descriptor );
                _methodBodies.Add(methodBody, smb);
            }
        }
        /// <summary>
        /// </summary>
        /// <param name="type">
        /// </param>
        /// <param name="typeResolver">
        /// </param>
        public SynthesizedMultiDimArraySetMethod(IType type, ITypeResolver typeResolver)
            : base("Set", type, typeResolver.System.System_Void)
        {
            object[] code;
            IList<object> tokenResolutions;
            IList<IType> locals;
            IList<IParameter> parameters;
            ArrayMultiDimensionGen.GetMultiDimensionArraySet(type, typeResolver, out code, out tokenResolutions, out locals, out parameters);

            this._methodBody = new SynthesizedMethodBodyDecorator(
                null,
                locals,
                MethodBodyBank.Transform(code).ToArray());

            this._parameters = parameters;
            this._tokenResolutions = tokenResolutions;
        }
示例#21
0
    public override void Traverse(IMethodBody methodBody) {
      sourceEmitterOutput.WriteLine("");
      if (this.pdbReader != null)
        PrintScopes(methodBody);
      else
        PrintLocals(methodBody.LocalVariables);

      this.cdfg = ControlAndDataFlowGraph<BasicBlock<Instruction>, Instruction>.GetControlAndDataFlowGraphFor(host, methodBody, this.pdbReader);
      var numberOfBlocks = this.cdfg.BlockFor.Count;

      foreach (var block in this.cdfg.AllBlocks) {
        this.PrintBlock(block);
      }

      sourceEmitterOutput.WriteLine("**************************************************************");
      sourceEmitterOutput.WriteLine();
    }
        /// <summary>
        /// </summary>
        /// <param name="type">
        /// </param>
        /// <param name="typeResolver">
        /// </param>
        public SynthesizedEnumToStringMethod(IType type, ITypeResolver typeResolver)
            : base("ToString", type, typeResolver.System.System_String, isOverride: true)
        {
            object[] code;
            IList<object> tokenResolutions;
            IList<IType> locals;
            IList<IParameter> parameters;
            EnumGen.GetEnumToStringMethod(type, typeResolver, out code, out tokenResolutions, out locals, out parameters);

            this._methodBody = new SynthesizedMethodBodyDecorator(
                null,
                locals,
                MethodBodyBank.Transform(code).ToArray());

            this._parameters = parameters;
            this._tokenResolutions = tokenResolutions;
        }
示例#23
0
        /// <summary>
        /// Tries to get the first field reference in the method body
        /// </summary>
        /// <param name="body"></param>
        /// <param name="field"></param>
        /// <returns></returns>
        public static bool TryGetFirstFieldReference(IMethodBody body, out IFieldReference field)
        {
            Contract.Requires(body != null);
            Contract.Ensures(!Contract.Result<bool>() || Contract.ValueAtReturn(out field) != null);

            foreach (var operation in body.Operations)
            {
                if (operation.OperationCode == OperationCode.Stfld ||
                    operation.OperationCode == OperationCode.Ldfld)
                {
                    field = (IFieldReference)operation.Value;
                    return field != null;
                }
            }

            field = null;
            return false;
        }
            public override void Traverse(IMethodBody methodBody)
            {
                PrintToken(CSharpToken.LeftCurly);

                ISourceMethodBody/*?*/ sourceMethodBody = methodBody as ISourceMethodBody;
                if (sourceMethodBody == null)
                {
                    var options = DecompilerOptions.Loops;
                    if (!printCompilerGeneratedMembers)
                        options |= (DecompilerOptions.AnonymousDelegates | DecompilerOptions.Iterators);
                    sourceMethodBody = new SourceMethodBody(methodBody, host, pdbReader, pdbReader, options);
                }
                if (noIL)
                    Traverse(sourceMethodBody.Block.Statements);
                else
                {
                   // this.Traverse(sourceMethodBody.Block);
                  //  PrintToken(CSharpToken.NewLine);

                    if (pdbReader != null)
                        PrintScopes(methodBody);
                    else
                        PrintLocals(methodBody.LocalVariables);

                    int currentIndex = -1; // a number no index matches
                    foreach (IOperation operation in methodBody.Operations)
                    {
                        if (pdbReader != null)
                        {
                            foreach (IPrimarySourceLocation psloc in pdbReader.GetPrimarySourceLocationsFor(operation.Location))
                            {
                                if (psloc.StartIndex != currentIndex)
                                {
                                    PrintSourceLocation(psloc);
                                    currentIndex = psloc.StartIndex;
                                }
                            }
                        }
                        PrintOperation(operation);
                    }
                }

                PrintToken(CSharpToken.RightCurly);
            }
        /// <summary>
        /// </summary>
        /// <param name="type">
        /// </param>
        /// <param name="typeResolver">
        /// </param>
        public SynthesizedMultiDimArrayCtorMethod(IType arrayType, ITypeResolver typeResolver)
            : base(arrayType, ".ctor")
        {
            this.typeResolver = typeResolver;

            object[] code;
            IList<object> tokenResolutions;
            IList<IType> locals;
            IList<IParameter> parameters;
            ArrayMultiDimensionGen.GetMultiDimensionArrayCtor(arrayType, typeResolver, out code, out tokenResolutions, out locals, out parameters);

            this._methodBody = new SynthesizedMethodBodyDecorator(
                null,
                locals,
                MethodBodyBank.Transform(code).ToArray());

            this._parameters = parameters;
            this._tokenResolutions = tokenResolutions;
        }
    public override void TraverseChildren(IMethodBody methodBody) {
      if (this.pdbReader != null)
        this.PrintScopes(methodBody);
      else
        this.PrintLocals(methodBody.LocalVariables);

      int currentIndex = -1; // a number no index matches
      foreach (IOperation operation in methodBody.Operations) {
        if (this.pdbReader != null) {
          foreach (IPrimarySourceLocation psloc in this.pdbReader.GetPrimarySourceLocationsFor(operation.Location)) {
            if (psloc.StartIndex != currentIndex) {
              this.PrintSourceLocation(psloc);
              currentIndex = psloc.StartIndex;
            }
          }
        }
        this.PrintOperation(operation);
      }
    }
        // TODO: Add support for fields, properties, type definitions and attributes as well
        // 
        // Example:
        //  [Serializable]
        //  public class Foo {}
        //
        // The 'Serializable' (Which is not supported on most platforms) is not found

        public override void Visit(IMethodBody method)
        {
            var calls = method.Operations
                              .Where(opcode => opcode.OperationCode == OperationCode.Call
                                            || opcode.OperationCode == OperationCode.Callvirt
                                            || opcode.OperationCode == OperationCode.Newobj);

            var foundInterestingCall = false;
            foreach (var call in calls)
            {
                var calledMethod = (IMethodReference)call.Value;
                var calledId = calledMethod.DocId();

                MissingMemberInfo memberInfo = null;
                if (!_interestingMethods.TryGetValue(calledId, out memberInfo))
                {
                    // Try again with unwrapped member
                    var unwrappedId = calledMethod.UnWrapMember().DocId();
                    _interestingMethods.TryGetValue(unwrappedId, out memberInfo);
                }

                if (memberInfo != null)
                {
                    foundInterestingCall = true;

                    var sourceItems = _pdbReader
                        .GetClosestPrimarySourceLocationsFor(call.Location)
                        .Select(l => GetSourceMappedItem(l, memberInfo));

                    _foundItems.AddRange(sourceItems);
                }
            }

            // Check signature for interesting return type to catch polymorphic returns
            // TODO: Does this condition need to be met? Should we check every return type?
            if (!foundInterestingCall)
            {
                CheckReturnType(method);
            }

            base.Visit(method);
        }
        /// <summary>
        /// </summary>
        /// <param name="type">
        /// </param>
        /// <param name="typeResolver">
        /// </param>
        public SynthesizedSingleDimArrayIListGetCountMethod(IType arrayType, ITypeResolver typeResolver)
            : base("get_Count", arrayType, typeResolver.System.System_Int32)
        {
            var codeList = new IlCodeBuilder();
            codeList.LoadArgument(0);
            codeList.Add(Code.Ldlen);
            codeList.Add(Code.Ret);

            var locals = new List<IType>();

            this._methodBody =
                new SynthesizedMethodBodyDecorator(
                    null,
                    locals,
                    codeList.GetCode());

            this._parameters = new List<IParameter>();

            this._tokenResolutions = new List<object>();
        }
示例#29
0
        /// <summary>
        /// Returns true if the namespace scope for this method should be forwarded to another method.
        /// Returns non-null <paramref name="forwardToMethod"/> if the forwarding should be done directly via UsingNamespace,
        /// null if the forwarding is done via custom debug info.
        /// </summary>
        public bool ShouldForwardNamespaceScopes(EmitContext context, IMethodBody methodBody, uint methodToken, out IMethodDefinition forwardToMethod)
        {
            if (ShouldForwardToPreviousMethodWithUsingInfo(context, methodBody) || methodBody.ImportScope == null)
            {
                // SerializeNamespaceScopeMetadata will do the actual forwarding in case this is a CSharp method.
                // VB on the other hand adds a "@methodtoken" to the scopes instead.
                if (context.Module.GenerateVisualBasicStylePdb)
                {
                    forwardToMethod = _previousMethodBodyWithUsingInfo.MethodDefinition;
                }
                else
                {
                    forwardToMethod = null;
                }

                return true;
            }

            _previousMethodBodyWithUsingInfo = methodBody;
            _previousMethodTokenWithUsingInfo = methodToken;
            forwardToMethod = null;
            return false;
        }
示例#30
0
    /// <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, localScopeProvider) {
      Contract.Requires(ilMethodBody != null);
      Contract.Requires(host != null);

      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;
      if (IteratorHelper.EnumerableIsNotEmpty(ilMethodBody.LocalVariables))
        this.LocalsAreZeroed = ilMethodBody.LocalsAreZeroed;
      else
        this.LocalsAreZeroed = true;
      this.MethodDefinition = ilMethodBody.MethodDefinition;
      this.privateHelperFieldsToRemove = null;
      this.privateHelperMethodsToRemove = null;
      this.privateHelperTypesToRemove = null;
      this.cdfg = ControlAndDataFlowGraph<BasicBlock<Instruction>, Instruction>.GetControlAndDataFlowGraphFor(host, ilMethodBody, localScopeProvider);
    }
示例#31
0
        private void SerializeMethodDebugInfo(
            IMethodBody bodyOpt,
            int methodRid,
            StandaloneSignatureHandle localSignatureHandleOpt,
            ref LocalVariableHandle lastLocalVariableHandle,
            ref LocalConstantHandle lastLocalConstantHandle
            )
        {
            if (bodyOpt == null)
            {
                _debugMetadataOpt.AddMethodDebugInformation(
                    default(DocumentHandle),
                    default(BlobHandle)
                    );
                return;
            }

            bool isKickoffMethod = bodyOpt.StateMachineTypeName != null;
            bool emitDebugInfo   = isKickoffMethod || !bodyOpt.SequencePoints.IsEmpty;

            if (!emitDebugInfo)
            {
                _debugMetadataOpt.AddMethodDebugInformation(
                    default(DocumentHandle),
                    default(BlobHandle)
                    );
                return;
            }

            var methodHandle = MetadataTokens.MethodDefinitionHandle(methodRid);

            var bodyImportScope   = bodyOpt.ImportScope;
            var importScopeHandle =
                (bodyImportScope != null)
                    ? GetImportScopeIndex(bodyImportScope, _scopeIndex)
                    : default(ImportScopeHandle);

            // documents & sequence points:
            DocumentHandle singleDocumentHandle;
            BlobHandle     sequencePointsBlob = SerializeSequencePoints(
                localSignatureHandleOpt,
                bodyOpt.SequencePoints,
                _documentIndex,
                out singleDocumentHandle
                );

            _debugMetadataOpt.AddMethodDebugInformation(
                document: singleDocumentHandle,
                sequencePoints: sequencePointsBlob
                );

            // Unlike native PDB we don't emit an empty root scope.
            // scopes are already ordered by StartOffset ascending then by EndOffset descending (the longest scope first).

            if (bodyOpt.LocalScopes.Length == 0)
            {
                // TODO: the compiler should produce a scope for each debuggable method
                _debugMetadataOpt.AddLocalScope(
                    method: methodHandle,
                    importScope: importScopeHandle,
                    variableList: NextHandle(lastLocalVariableHandle),
                    constantList: NextHandle(lastLocalConstantHandle),
                    startOffset: 0,
                    length: bodyOpt.IL.Length
                    );
            }
            else
            {
                foreach (LocalScope scope in bodyOpt.LocalScopes)
                {
                    _debugMetadataOpt.AddLocalScope(
                        method: methodHandle,
                        importScope: importScopeHandle,
                        variableList: NextHandle(lastLocalVariableHandle),
                        constantList: NextHandle(lastLocalConstantHandle),
                        startOffset: scope.StartOffset,
                        length: scope.Length
                        );

                    foreach (ILocalDefinition local in scope.Variables)
                    {
                        Debug.Assert(local.SlotIndex >= 0);

                        lastLocalVariableHandle = _debugMetadataOpt.AddLocalVariable(
                            attributes: local.PdbAttributes,
                            index: local.SlotIndex,
                            name: _debugMetadataOpt.GetOrAddString(local.Name)
                            );

                        SerializeLocalInfo(local, lastLocalVariableHandle);
                    }

                    foreach (ILocalDefinition constant in scope.Constants)
                    {
                        var mdConstant = constant.CompileTimeValue;
                        Debug.Assert(mdConstant != null);

                        lastLocalConstantHandle = _debugMetadataOpt.AddLocalConstant(
                            name: _debugMetadataOpt.GetOrAddString(constant.Name),
                            signature: SerializeLocalConstantSignature(constant)
                            );

                        SerializeLocalInfo(constant, lastLocalConstantHandle);
                    }
                }
            }

            var moveNextBodyInfo = bodyOpt.MoveNextBodyInfo;

            if (moveNextBodyInfo != null)
            {
                _debugMetadataOpt.AddStateMachineMethod(
                    moveNextMethod: methodHandle,
                    kickoffMethod: GetMethodDefinitionHandle(moveNextBodyInfo.KickoffMethod)
                    );

                if (moveNextBodyInfo is AsyncMoveNextBodyDebugInfo asyncInfo)
                {
                    SerializeAsyncMethodSteppingInfo(asyncInfo, methodHandle);
                }
            }

            SerializeStateMachineLocalScopes(bodyOpt, methodHandle);

            // delta doesn't need this information - we use information recorded by previous generation emit
            if (Context.Module.CommonCompilation.Options.EnableEditAndContinue && IsFullMetadata)
            {
                SerializeEncMethodDebugInformation(bodyOpt, methodHandle);
            }
        }
示例#32
0
 /// <summary>
 /// Returns zero or more local (block) scopes, each defining an IL range in which an iterator local is defined.
 /// The scopes are returned by the MoveNext method of the object returned by the iterator method.
 /// The index of the scope corresponds to the index of the local. Specifically local scope i corresponds
 /// to the local stored in field &lt;localName&gt;x_i of the class used to store the local values in between
 /// calls to MoveNext.
 /// </summary>
 public virtual IEnumerable <ILocalScope> GetIteratorScopes(IMethodBody methodBody)
 {
     return(Enumerable <ILocalScope> .Empty);
 }
示例#33
0
        public byte[] SerializeMethodDebugInfo(
            EmitContext context,
            IMethodBody methodBody,
            MethodDefinitionHandle methodHandle,
            bool emitStateMachineInfo,
            bool emitEncInfo,
            bool emitDynamicAndTupleInfo,
            out bool emitExternNamespaces)
        {
            emitExternNamespaces = false;

            // CONSIDER: this may not be the same "first" method as in Dev10, but
            // it shouldn't matter since all methods will still forward to a method
            // containing the appropriate information.
            if (_methodBodyWithModuleInfo == null)
            {
                // This module level information could go on every method (and does in
                // the edit-and-continue case), but - as an optimization - we'll just
                // put it on the first method we happen to encounter and then put a
                // reference to the first method's token in every other method (so they
                // can find the information).
                if (context.Module.GetAssemblyReferenceAliases(context).Any())
                {
                    _methodWithModuleInfo     = methodHandle;
                    _methodBodyWithModuleInfo = methodBody;
                    emitExternNamespaces      = true;
                }
            }

            var pooledBuilder = PooledBlobBuilder.GetInstance();
            var encoder       = new CustomDebugInfoEncoder(pooledBuilder);

            if (emitStateMachineInfo)
            {
                if (methodBody.StateMachineTypeName != null)
                {
                    encoder.AddStateMachineTypeName(methodBody.StateMachineTypeName);
                }
                else
                {
                    SerializeNamespaceScopeMetadata(ref encoder, context, methodBody);

                    encoder.AddStateMachineHoistedLocalScopes(methodBody.StateMachineHoistedLocalScopes);
                }
            }

            if (emitDynamicAndTupleInfo)
            {
                SerializeDynamicLocalInfo(ref encoder, methodBody);
                SerializeTupleElementNames(ref encoder, methodBody);
            }

            if (emitEncInfo)
            {
                var encMethodInfo = MetadataWriter.GetEncMethodDebugInfo(methodBody);
                SerializeCustomDebugInformation(ref encoder, encMethodInfo);
            }

            byte[] result = encoder.ToArray() ?? Array.Empty <byte>();
            pooledBuilder.Free();
            return(result);
        }
示例#34
0
        private static void SerializeTupleElementNames(ref CustomDebugInfoEncoder encoder, IMethodBody methodBody)
        {
            var locals = GetLocalInfoToSerialize(
                methodBody,
                local => !local.TupleElementNames.IsEmpty,
                (scope, local) => (local.Name, local.SlotIndex, scope.StartOffset, scope.EndOffset, local.TupleElementNames));

            if (locals == null)
            {
                return;
            }

            encoder.AddTupleElementNames(locals);

            locals.Free();
        }
示例#35
0
        /// <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)
        {
            Contract.Requires(host != null);
            Contract.Requires(methodBody != null);

            return(new Microsoft.Cci.ILToCodeModel.SourceMethodBody(methodBody, host, pdbReader, pdbReader, options));
        }
示例#36
0
        /// <summary>
        ///
        /// </summary>
        internal static ControlAndDataFlowGraph <BasicBlock, Instruction> SetupControlFlow(IMetadataHost host, IMethodBody methodBody, ILocalScopeProvider /*?*/ localScopeProvider = null)
        {
            Contract.Requires(host != null);
            Contract.Requires(methodBody != null);
            Contract.Ensures(Contract.Result <ControlAndDataFlowGraph <BasicBlock, Instruction> >() != null);

            var inferencer = new ControlFlowInferencer <BasicBlock, Instruction>(host, methodBody, localScopeProvider);

            return(inferencer.CreateBlocksAndEdges());
        }
示例#37
0
 public void SetMethodBody(IMethodBody body)
 {
     MethodBody = body;
 }
示例#38
0
        public byte[] SerializeMethodDebugInfo(EmitContext context, IMethodBody methodBody, int methodToken, bool isEncDelta, bool suppressNewCustomDebugInfo, out bool emitExternNamespaces)
        {
            emitExternNamespaces = false;

            // CONSIDER: this may not be the same "first" method as in Dev10, but
            // it shouldn't matter since all methods will still forward to a method
            // containing the appropriate information.
            if (_methodBodyWithModuleInfo == null) //UNDONE: || edit-and-continue
            {
                // This module level information could go on every method (and does in
                // the edit-and-continue case), but - as an optimization - we'll just
                // put it on the first method we happen to encounter and then put a
                // reference to the first method's token in every other method (so they
                // can find the information).
                if (context.Module.GetAssemblyReferenceAliases(context).Any())
                {
                    _methodTokenWithModuleInfo = methodToken;
                    _methodBodyWithModuleInfo  = methodBody;
                    emitExternNamespaces       = true;
                }
            }

            var customDebugInfo = ArrayBuilder <PooledBlobBuilder> .GetInstance();

            SerializeIteratorClassMetadata(methodBody, customDebugInfo);

            // NOTE: This is an attempt to match Dev10's apparent behavior.  For iterator methods (i.e. the method
            // that appears in source, not the synthesized ones), Dev10 only emits the ForwardIterator and IteratorLocal
            // custom debug info (e.g. there will be no information about the usings that were in scope).
            // NOTE: There seems to be an unusual behavior in ISymUnmanagedWriter where, if all the methods in a type are
            // iterator methods, no custom debug info is emitted for any method.  Adding a single non-iterator
            // method causes the custom debug info to be produced for all methods (including the iterator methods).
            // Since we are making the same ISymUnmanagedWriter calls as Dev10, we see the same behavior (i.e. this
            // is not a regression).
            if (methodBody.StateMachineTypeName == null)
            {
                SerializeNamespaceScopeMetadata(context, methodBody, customDebugInfo);
                SerializeStateMachineLocalScopes(methodBody, customDebugInfo);
            }

            if (!suppressNewCustomDebugInfo)
            {
                SerializeDynamicLocalInfo(methodBody, customDebugInfo);

                // delta doesn't need this information - we use information recorded by previous generation emit
                if (!isEncDelta)
                {
                    var encMethodInfo = MetadataWriter.GetEncMethodDebugInfo(methodBody);
                    SerializeCustomDebugInformation(encMethodInfo, customDebugInfo);
                }
            }

            byte[] result = SerializeCustomDebugMetadata(customDebugInfo);

            foreach (var builder in customDebugInfo)
            {
                builder.Free();
            }

            customDebugInfo.Free();

            return(result);
        }
示例#39
0
 /// <summary>
 /// Performs some computation with the given method body.
 /// </summary>
 public virtual void Visit(IMethodBody methodBody)
 {
 }
示例#40
0
        public static IMethodBase DefaultMethodWithBody(IMethodBody body)
        {
            var method = GeneralIMethodBase(DefaultMethodName, body);

            return(method.Object);
        }
示例#41
0
        public void SerializeDebugInfo(IMethodBody methodBody, uint localSignatureToken, CustomDebugInfoWriter customDebugInfoWriter)
        {
            Debug.Assert(_metadataWriter != null);

            bool isIterator    = methodBody.StateMachineTypeName != null;
            bool emitDebugInfo = isIterator || methodBody.HasAnySequencePoints;

            if (!emitDebugInfo)
            {
                return;
            }

            uint methodToken = _metadataWriter.GetMethodToken(methodBody.MethodDefinition);

            OpenMethod(methodToken);

            var localScopes = methodBody.LocalScopes;

            // CCI originally didn't have the notion of the default scope that is open
            // when a method is opened. In order to reproduce CSC PDBs, this must be added. Otherwise
            // a seemingly unnecessary scope that contains only other scopes is put in the PDB.
            if (localScopes.Length > 0)
            {
                this.DefineScopeLocals(localScopes[0], localSignatureToken);
            }

            // NOTE: This is an attempt to match Dev10's apparent behavior.  For iterator methods (i.e. the method
            // that appears in source, not the synthesized ones), Dev10 only emits the ForwardIterator and IteratorLocal
            // custom debug info (e.g. there will be no information about the usings that were in scope).
            if (!isIterator)
            {
                IMethodDefinition forwardToMethod;
                if (customDebugInfoWriter.ShouldForwardNamespaceScopes(methodBody, methodToken, out forwardToMethod))
                {
                    if (forwardToMethod != null)
                    {
                        string usingString = "@" + _metadataWriter.GetMethodToken(forwardToMethod);
                        Debug.Assert(!_metadataWriter.IsUsingStringTooLong(usingString));
                        UsingNamespace(usingString, methodBody.MethodDefinition.Name);
                    }
                    // otherwise, the forwarding is done via custom debug info
                }
                else
                {
                    this.DefineNamespaceScopes(methodBody);
                }
            }

            DefineLocalScopes(localScopes, localSignatureToken);

            EmitSequencePoints(methodBody.GetSequencePoints());

            AsyncMethodBodyDebugInfo asyncDebugInfo = methodBody.AsyncDebugInfo;

            if (asyncDebugInfo != null)
            {
                SetAsyncInfo(
                    methodToken,
                    _metadataWriter.GetMethodToken(asyncDebugInfo.KickoffMethod),
                    asyncDebugInfo.CatchHandlerOffset,
                    asyncDebugInfo.YieldOffsets,
                    asyncDebugInfo.ResumeOffsets);
            }

            var context            = _metadataWriter.Context;
            var module             = context.Module;
            var compilationOptions = context.ModuleBuilder.CommonCompilation.Options;

            // We need to avoid emitting CDI DynamicLocals = 5 and EditAndContinueLocalSlotMap = 6 for files processed by WinMDExp until
            // bug #1067635 is fixed and available in SDK.
            bool suppressNewCustomDebugInfo = !compilationOptions.ExtendedCustomDebugInformation ||
                                              (compilationOptions.OutputKind == OutputKind.WindowsRuntimeMetadata);

            bool emitEncInfo = compilationOptions.EnableEditAndContinue && !_metadataWriter.IsFullMetadata;

            bool emitExternNamespaces;

            byte[] blob = customDebugInfoWriter.SerializeMethodDebugInfo(module, methodBody, methodToken, emitEncInfo, suppressNewCustomDebugInfo, out emitExternNamespaces);
            if (blob != null)
            {
                DefineCustomMetadata("MD2", blob);
            }

            if (emitExternNamespaces)
            {
                this.DefineExternAliases(module);
            }

            // TODO: it's not clear why we are closing a scope here with IL length:
            CloseScope((uint)methodBody.IL.Length);

            CloseMethod();
        }
示例#42
0
        private static void SerializeDynamicLocalInfo(ref CustomDebugInfoEncoder encoder, IMethodBody methodBody)
        {
            if (!methodBody.HasDynamicLocalVariables)
            {
                return;
            }

            byte[] GetDynamicFlags(ILocalDefinition local)
            {
                var dynamicTransformFlags = local.DynamicTransformFlags;
                var flags = new byte[CustomDebugInfoEncoder.DynamicAttributeSize];

                for (int k = 0; k < dynamicTransformFlags.Length; k++)
                {
                    if (dynamicTransformFlags[k])
                    {
                        flags[k] = 1;
                    }
                }

                return(flags);
            }

            var dynamicLocals = GetLocalInfoToSerialize(
                methodBody,
                local =>
            {
                var dynamicTransformFlags = local.DynamicTransformFlags;
                return(!dynamicTransformFlags.IsEmpty &&
                       dynamicTransformFlags.Length <= CustomDebugInfoEncoder.DynamicAttributeSize &&
                       local.Name.Length < CustomDebugInfoEncoder.IdentifierSize);
            },
                (scope, local) => (local.Name, GetDynamicFlags(local), local.DynamicTransformFlags.Length, (local.SlotIndex < 0) ? 0 : local.SlotIndex));

            if (dynamicLocals == null)
            {
                return;
            }

            encoder.AddDynamicLocals(dynamicLocals);
            dynamicLocals.Free();
        }
示例#43
0
 public virtual void Visit(IMethodBody methodBody)
 {
     this.Visit(methodBody.LocalVariables);
     //this.Visit(methodBody.Operations);    //in Roslyn we don't break out each instruction as it's own operation.
     this.Visit(methodBody.ExceptionRegions);
 }
示例#44
0
 private static void SerializeIteratorClassMetadata(IMethodBody methodBody, ArrayBuilder <BlobWriter> customDebugInfo)
 {
     SerializeReferenceToIteratorClass(methodBody.StateMachineTypeName, customDebugInfo);
 }
示例#45
0
        public static IMethodBase Method(string identifier, IMethodBody body)
        {
            var method = GeneralIMethodBase(identifier, body);

            return(method.Object);
        }
        /// <summary>
        /// Constructs a control and data flow graph for the given method body.
        /// </summary>
        public static ControlAndDataFlowGraph <BasicBlock, Instruction> GetControlAndDataFlowGraphFor(IMetadataHost host, IMethodBody methodBody, ILocalScopeProvider /*?*/ localScopeProvider = null)
        {
            Contract.Requires(host != null);
            Contract.Requires(methodBody != null);
            Contract.Ensures(Contract.Result <ControlAndDataFlowGraph <BasicBlock, Instruction> >() != null);

            var cdfg = ControlFlowInferencer <BasicBlock, Instruction> .SetupControlFlow(host, methodBody, localScopeProvider);

            DataFlowInferencer <BasicBlock, Instruction> .SetupDataFlow(host, methodBody, cdfg);

            TypeInferencer <BasicBlock, Instruction> .FillInTypes(host, cdfg);

            return(cdfg);
        }
示例#47
0
        private void DefineNamespaceScopes(IMethodBody methodBody)
        {
            var  module        = Module;
            bool isVisualBasic = module.GenerateVisualBasicStylePdb;

            IMethodDefinition method = methodBody.MethodDefinition;

            var namespaceScopes = methodBody.ImportScope;

            PooledHashSet <string> lazyDeclaredExternAliases = null;

            if (!isVisualBasic)
            {
                for (var scope = namespaceScopes; scope != null; scope = scope.Parent)
                {
                    foreach (var import in scope.GetUsedNamespaces(Context))
                    {
                        if (import.TargetNamespaceOpt == null && import.TargetTypeOpt == null)
                        {
                            Debug.Assert(import.AliasOpt != null);
                            Debug.Assert(import.TargetAssemblyOpt == null);

                            if (lazyDeclaredExternAliases == null)
                            {
                                lazyDeclaredExternAliases = PooledHashSet <string> .GetInstance();
                            }

                            lazyDeclaredExternAliases.Add(import.AliasOpt);
                        }
                    }
                }
            }

            // file and namespace level
            for (IImportScope scope = namespaceScopes; scope != null; scope = scope.Parent)
            {
                foreach (UsedNamespaceOrType import in scope.GetUsedNamespaces(Context))
                {
                    var importString = TryEncodeImport(import, lazyDeclaredExternAliases, isProjectLevel: false);
                    if (importString != null)
                    {
                        UsingNamespace(importString, method);
                    }
                }
            }

            lazyDeclaredExternAliases?.Free();

            // project level
            if (isVisualBasic)
            {
                string defaultNamespace = module.DefaultNamespace;

                if (defaultNamespace != null)
                {
                    // VB marks the default/root namespace with an asterisk
                    UsingNamespace("*" + defaultNamespace, module);
                }

                foreach (string assemblyName in module.LinkedAssembliesDebugInfo)
                {
                    UsingNamespace("&" + assemblyName, module);
                }

                foreach (UsedNamespaceOrType import in module.GetImports(Context))
                {
                    var importString = TryEncodeImport(import, null, isProjectLevel: true);
                    if (importString != null)
                    {
                        UsingNamespace(importString, method);
                    }
                }

                // VB current namespace -- VB appends the namespace of the container without prefixes
                UsingNamespace(GetOrCreateSerializedNamespaceName(method.ContainingNamespace), method);
            }
        }
        /// <summary>
        /// Returns true if the method body is an iterator, in which case the scope information should be retrieved from the object
        /// returned by the method.
        /// </summary>
        public bool IsIterator(IMethodBody methodBody)
        {
            PdbFunction /*?*/ pdbFunction = this.GetPdbFunctionFor(methodBody);

            return(pdbFunction != null && pdbFunction.iteratorClass != null);
        }
示例#49
0
        public void SerializeDebugInfo(IMethodBody methodBody, uint localSignatureToken, CustomDebugInfoWriter customDebugInfoWriter)
        {
            Debug.Assert(_metadataWriter != null);

            bool isIterator    = methodBody.StateMachineTypeName != null;
            bool emitDebugInfo = isIterator || methodBody.HasAnySequencePoints;

            if (!emitDebugInfo)
            {
                return;
            }

            uint methodToken = _metadataWriter.GetMethodToken(methodBody.MethodDefinition);

            OpenMethod(methodToken);

            var localScopes = methodBody.LocalScopes;

            // Open the outer-most language defined scope, the namespace scopes will be emitted to it.
            // Note that the root scope has already been open, but native compilers leave it empty.
            if (localScopes.Length > 0)
            {
                this.DefineScopeLocals(localScopes[0], localSignatureToken);
            }

            // NOTE: This is an attempt to match Dev10's apparent behavior.  For iterator methods (i.e. the method
            // that appears in source, not the synthesized ones), Dev10 only emits the ForwardIterator and IteratorLocal
            // custom debug info (e.g. there will be no information about the usings that were in scope).
            if (!isIterator)
            {
                IMethodDefinition forwardToMethod;
                if (customDebugInfoWriter.ShouldForwardNamespaceScopes(Context, methodBody, methodToken, out forwardToMethod))
                {
                    if (forwardToMethod != null)
                    {
                        UsingNamespace("@" + _metadataWriter.GetMethodToken(forwardToMethod), methodBody.MethodDefinition);
                    }
                    // otherwise, the forwarding is done via custom debug info
                }
                else
                {
                    this.DefineNamespaceScopes(methodBody);
                }
            }

            DefineLocalScopes(localScopes, localSignatureToken);

            EmitSequencePoints(methodBody.GetSequencePoints());

            AsyncMethodBodyDebugInfo asyncDebugInfo = methodBody.AsyncDebugInfo;

            if (asyncDebugInfo != null)
            {
                SetAsyncInfo(
                    methodToken,
                    _metadataWriter.GetMethodToken(asyncDebugInfo.KickoffMethod),
                    asyncDebugInfo.CatchHandlerOffset,
                    asyncDebugInfo.YieldOffsets,
                    asyncDebugInfo.ResumeOffsets);
            }

            var compilationOptions = Context.ModuleBuilder.CommonCompilation.Options;

            // We need to avoid emitting CDI DynamicLocals = 5 and EditAndContinueLocalSlotMap = 6 for files processed by WinMDExp until
            // bug #1067635 is fixed and available in SDK.
            bool suppressNewCustomDebugInfo = !compilationOptions.ExtendedCustomDebugInformation ||
                                              (compilationOptions.OutputKind == OutputKind.WindowsRuntimeMetadata);

            bool emitEncInfo = compilationOptions.EnableEditAndContinue && !_metadataWriter.IsFullMetadata;

            bool emitExternNamespaces;

            byte[] blob = customDebugInfoWriter.SerializeMethodDebugInfo(Context, methodBody, methodToken, emitEncInfo, suppressNewCustomDebugInfo, out emitExternNamespaces);
            if (blob != null)
            {
                DefineCustomMetadata("MD2", blob);
            }

            if (emitExternNamespaces)
            {
                this.DefineAssemblyReferenceAliases();
            }

            CloseMethod(methodBody.IL.Length);
        }
 /// <summary>
 /// Allocates a range of CLR IL operations that comprise a lexical scope, specified as an IL offset and a length.
 /// </summary>
 internal PdbLocalScope(IMethodBody methodBody, PdbScope pdbScope)
 {
     this.methodBody = methodBody;
     this.pdbScope   = pdbScope;
 }
示例#51
0
        private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder <BlobWriter> customDebugInfo)
        {
            if (!methodBody.HasDynamicLocalVariables)
            {
                return; //There are no dynamic locals
            }

            var dynamicLocals = ArrayBuilder <ILocalDefinition> .GetInstance();

            foreach (ILocalDefinition local in methodBody.LocalVariables)
            {
                if (local.IsDynamic)
                {
                    dynamicLocals.Add(local);
                }
            }

            int dynamicVariableCount = dynamicLocals.Count;

            foreach (var currentScope in methodBody.LocalScopes)
            {
                foreach (var localConstant in currentScope.Constants)
                {
                    if (localConstant.IsDynamic)
                    {
                        dynamicLocals.Add(localConstant);
                    }
                }
            }

            Debug.Assert(dynamicLocals.Any()); // There must be at least one dynamic local if this point is reached

            const int blobSize = 200;          //DynamicAttribute - 64, DynamicAttributeLength - 4, SlotIndex -4, IdentifierName - 128
            var       cmw      = new BlobWriter();

            cmw.WriteByte(CDI.CdiVersion);
            cmw.WriteByte(CDI.CdiKindDynamicLocals);
            cmw.Align(4);
            // size = Version,Kind + size + cBuckets + (dynamicCount * sizeOf(Local Blob))
            cmw.WriteUint(4 + 4 + 4 + (uint)dynamicLocals.Count * blobSize);//Size of the Dynamic Block
            cmw.WriteUint((uint)dynamicLocals.Count);

            int localIndex = 0;

            foreach (ILocalDefinition local in dynamicLocals)
            {
                if (local.Name.Length > 63)//Ignore and push empty information
                {
                    cmw.WriteBytes(0, blobSize);
                    continue;
                }

                var dynamicTransformFlags = local.DynamicTransformFlags;
                if (!dynamicTransformFlags.IsDefault && dynamicTransformFlags.Length <= 64)
                {
                    byte[] flag = new byte[64];
                    for (int k = 0; k < dynamicTransformFlags.Length; k++)
                    {
                        if ((bool)dynamicTransformFlags[k].Value)
                        {
                            flag[k] = 1;
                        }
                    }
                    cmw.WriteBytes(flag);                              //Written Flag
                    cmw.WriteUint((uint)dynamicTransformFlags.Length); //Written Length
                }
                else
                {
                    cmw.WriteBytes(0, 68); //Empty flag array and size.
                }

                if (localIndex < dynamicVariableCount)
                {
                    // Dynamic variable
                    cmw.WriteUint((uint)local.SlotIndex);
                }
                else
                {
                    // Dynamic constant
                    cmw.WriteUint(0);
                }

                char[] localName = new char[64];
                local.Name.CopyTo(0, localName, 0, local.Name.Length);
                cmw.WriteUTF16(localName);

                localIndex++;
            }

            dynamicLocals.Free();
            customDebugInfo.Add(cmw);
        }
示例#52
0
        protected virtual void EmitMethodBody(IMethodBody methodBody)
        {
            Contract.Requires(methodBody != null);

            var savedLabelFor = this.labelFor;

            this.labelFor = new Hashtable <ILGeneratorLabel>();
            var initialScopeStackCount = this.scopeStack.Count;

            foreach (var exceptionInfo in methodBody.OperationExceptionInformation)
            {
                Contract.Assume(exceptionInfo != null);
                this.Generator.AddExceptionHandlerInformation(exceptionInfo.HandlerKind, exceptionInfo.ExceptionType,
                                                              this.GetLabelFor(exceptionInfo.TryStartOffset), this.GetLabelFor(exceptionInfo.TryEndOffset),
                                                              this.GetLabelFor(exceptionInfo.HandlerStartOffset), this.GetLabelFor(exceptionInfo.HandlerEndOffset),
                                                              exceptionInfo.HandlerKind == HandlerKind.Filter ? this.GetLabelFor(exceptionInfo.FilterDecisionStartOffset) : null);
            }

            if (this.localScopeProvider == null)
            {
                foreach (var localDef in methodBody.LocalVariables)
                {
                    Contract.Assume(localDef != null);
                    this.Generator.AddVariableToCurrentScope(localDef);
                }
            }
            else
            {
                foreach (var ns in this.localScopeProvider.GetNamespaceScopes(methodBody))
                {
                    Contract.Assume(ns != null);
                    foreach (var uns in ns.UsedNamespaces)
                    {
                        Contract.Assume(uns != null);
                        this.Generator.UseNamespace(uns.NamespaceName.Value);
                    }
                }
                this.scopeEnumerator                = this.localScopeProvider.GetLocalScopes(methodBody).GetEnumerator();
                this.scopeEnumeratorIsValid         = this.scopeEnumerator.MoveNext();
                this.iteratorScopeEnumerator        = this.localScopeProvider.GetIteratorScopes(methodBody).GetEnumerator();
                this.iteratorScopeEnumeratorIsValid = this.iteratorScopeEnumerator.MoveNext();
                if (this.synchronizationInfo != null)
                {
                    this.syncPointEnumerator        = this.synchronizationInfo.SynchronizationPoints.GetEnumerator();
                    this.syncPointEnumeratorIsValid = this.syncPointEnumerator.MoveNext();
                }
            }

            foreach (var operation in methodBody.Operations)
            {
                switch (operation.OperationCode)
                {
                case OperationCode.Beq:
                case OperationCode.Bge:
                case OperationCode.Bge_Un:
                case OperationCode.Bgt:
                case OperationCode.Bgt_Un:
                case OperationCode.Ble:
                case OperationCode.Ble_Un:
                case OperationCode.Blt:
                case OperationCode.Blt_Un:
                case OperationCode.Bne_Un:
                case OperationCode.Br:
                case OperationCode.Br_S:
                case OperationCode.Brfalse:
                case OperationCode.Brtrue:
                case OperationCode.Leave:
                case OperationCode.Beq_S:
                case OperationCode.Bge_S:
                case OperationCode.Bge_Un_S:
                case OperationCode.Bgt_S:
                case OperationCode.Bgt_Un_S:
                case OperationCode.Ble_S:
                case OperationCode.Ble_Un_S:
                case OperationCode.Blt_S:
                case OperationCode.Blt_Un_S:
                case OperationCode.Bne_Un_S:
                case OperationCode.Brfalse_S:
                case OperationCode.Brtrue_S:
                case OperationCode.Leave_S:
                    Contract.Assume(operation.Value is uint);
                    this.GetLabelFor((uint)operation.Value);
                    break;

                case OperationCode.Switch:
                    uint[] offsets = operation.Value as uint[];
                    Contract.Assume(offsets != null);
                    foreach (var offset in offsets)
                    {
                        this.GetLabelFor(offset);
                    }
                    break;
                }
            }

            foreach (var operation in methodBody.Operations)
            {
                Contract.Assume(operation != null);
                Contract.Assume(this.labelFor != null);
                var label = this.labelFor.Find(operation.Offset);
                if (label != null)
                {
                    this.Generator.MarkLabel(label);
                }
                this.EmitDebugInformationFor(operation);
                this.EmitOperation(operation);
                this.TrackLocal(operation.Value);
            }

            while (this.scopeStack.Count > initialScopeStackCount)
            {
                this.Generator.EndScope();
                this.scopeStack.Pop();
            }

            this.labelFor = savedLabelFor;
            Contract.Assume(this.generator != null);
        }
示例#53
0
        private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder <PooledBlobBuilder> customDebugInfo)
        {
            if (!methodBody.HasDynamicLocalVariables)
            {
                return; //There are no dynamic locals
            }

            const int dynamicAttributeSize = 64;
            const int identifierSize       = 64;

            var dynamicLocals = GetLocalInfoToSerialize(
                methodBody,
                local =>
            {
                var dynamicTransformFlags = local.DynamicTransformFlags;
                return(!dynamicTransformFlags.IsEmpty &&
                       dynamicTransformFlags.Length <= dynamicAttributeSize &&
                       local.Name.Length < identifierSize);
            },
                (scope, local) => local);

            if (dynamicLocals == null)
            {
                return;
            }

            const int blobSize = dynamicAttributeSize + 4 + 4 + identifierSize * 2;//DynamicAttribute: 64, DynamicAttributeLength: 4, SlotIndex: 4, IdentifierName: 128
            var       cmw      = PooledBlobBuilder.GetInstance();

            cmw.WriteByte(CustomDebugInfoConstants.Version);
            cmw.WriteByte((byte)CustomDebugInfoKind.DynamicLocals);
            cmw.Align(4);
            // size = Version,Kind + size + cBuckets + (dynamicCount * sizeOf(Local Blob))
            cmw.WriteUInt32(4 + 4 + 4 + (uint)dynamicLocals.Count * blobSize);//Size of the Dynamic Block
            cmw.WriteUInt32((uint)dynamicLocals.Count);

            foreach (ILocalDefinition local in dynamicLocals)
            {
                var    dynamicTransformFlags = local.DynamicTransformFlags;
                byte[] flag = new byte[dynamicAttributeSize];
                for (int k = 0; k < dynamicTransformFlags.Length; k++)
                {
                    if ((bool)dynamicTransformFlags[k].Value)
                    {
                        flag[k] = 1;
                    }
                }
                cmw.WriteBytes(flag);                                //Written Flag
                cmw.WriteUInt32((uint)dynamicTransformFlags.Length); //Written Length

                var localIndex = local.SlotIndex;
                cmw.WriteUInt32((localIndex < 0) ? 0u : (uint)localIndex);

                char[] localName = new char[identifierSize];
                local.Name.CopyTo(0, localName, 0, local.Name.Length);
                cmw.WriteUTF16(localName);
            }

            dynamicLocals.Free();
            customDebugInfo.Add(cmw);
        }
示例#54
0
        private void SerializeNamespaceScopeMetadata(ref CustomDebugInfoEncoder encoder, EmitContext context, IMethodBody methodBody)
        {
            if (context.Module.GenerateVisualBasicStylePdb)
            {
                return;
            }

            if (ShouldForwardToPreviousMethodWithUsingInfo(context, methodBody))
            {
                Debug.Assert(!ReferenceEquals(_previousMethodBodyWithUsingInfo, methodBody));
                encoder.AddForwardMethodInfo(_previousMethodWithUsingInfo);
                return;
            }

            var usingCounts = ArrayBuilder <int> .GetInstance();

            for (IImportScope scope = methodBody.ImportScope; scope != null; scope = scope.Parent)
            {
                usingCounts.Add(scope.GetUsedNamespaces().Length);
            }

            encoder.AddUsingGroups(usingCounts);
            usingCounts.Free();

            if (_methodBodyWithModuleInfo != null && !ReferenceEquals(_methodBodyWithModuleInfo, methodBody))
            {
                encoder.AddForwardModuleInfo(_methodWithModuleInfo);
            }
        }
示例#55
0
 /// <summary>
 /// Returns true if the method body is an iterator.
 /// </summary>
 public virtual bool IsIterator(IMethodBody methodBody)
 {
     return(false);
 }
示例#56
0
        private void SerializeMethodDebugInfo(IMethodBody bodyOpt, int methodRid, int localSignatureRowId)
        {
            if (bodyOpt == null)
            {
                _methodDebugInformationTable.Add(default(MethodDebugInformationRow));
                return;
            }

            bool isIterator    = bodyOpt.StateMachineTypeName != null;
            bool emitDebugInfo = isIterator || bodyOpt.HasAnySequencePoints;

            if (!emitDebugInfo)
            {
                _methodDebugInformationTable.Add(default(MethodDebugInformationRow));
                return;
            }

            var bodyImportScope = bodyOpt.ImportScope;
            int importScopeRid  = (bodyImportScope != null) ? GetImportScopeIndex(bodyImportScope, _scopeIndex) : 0;

            // documents & sequence points:
            int     singleDocumentRowId;
            BlobIdx sequencePointsBlob = SerializeSequencePoints(localSignatureRowId, bodyOpt.GetSequencePoints(), _documentIndex, out singleDocumentRowId);

            _methodDebugInformationTable.Add(new MethodDebugInformationRow {
                Document = (uint)singleDocumentRowId, SequencePoints = sequencePointsBlob
            });

            // Unlike native PDB we don't emit an empty root scope.
            // scopes are already ordered by StartOffset ascending then by EndOffset descending (the longest scope first).

            if (bodyOpt.LocalScopes.Length == 0)
            {
                // TODO: the compiler should produce a scope for each debuggable method
                _localScopeTable.Add(new LocalScopeRow
                {
                    Method       = (uint)methodRid,
                    ImportScope  = (uint)importScopeRid,
                    VariableList = (uint)_localVariableTable.Count + 1,
                    ConstantList = (uint)_localConstantTable.Count + 1,
                    StartOffset  = 0,
                    Length       = (uint)bodyOpt.IL.Length
                });
            }
            else
            {
                foreach (LocalScope scope in bodyOpt.LocalScopes)
                {
                    _localScopeTable.Add(new LocalScopeRow
                    {
                        Method       = (uint)methodRid,
                        ImportScope  = (uint)importScopeRid,
                        VariableList = (uint)_localVariableTable.Count + 1,
                        ConstantList = (uint)_localConstantTable.Count + 1,
                        StartOffset  = (uint)scope.StartOffset,
                        Length       = (uint)scope.Length
                    });

                    foreach (ILocalDefinition local in scope.Variables)
                    {
                        Debug.Assert(local.SlotIndex >= 0);

                        _localVariableTable.Add(new LocalVariableRow
                        {
                            Attributes = (ushort)local.PdbAttributes,
                            Index      = (ushort)local.SlotIndex,
                            Name       = _debugHeapsOpt.GetStringIndex(local.Name)
                        });

                        SerializeDynamicLocalInfo(local, rowId: _localVariableTable.Count, isConstant: false);
                    }

                    foreach (ILocalDefinition constant in scope.Constants)
                    {
                        var mdConstant = constant.CompileTimeValue;
                        Debug.Assert(mdConstant != null);

                        _localConstantTable.Add(new LocalConstantRow
                        {
                            Name      = _debugHeapsOpt.GetStringIndex(constant.Name),
                            Signature = SerializeLocalConstantSignature(constant)
                        });

                        SerializeDynamicLocalInfo(constant, rowId: _localConstantTable.Count, isConstant: true);
                    }
                }
            }

            var asyncDebugInfo = bodyOpt.AsyncDebugInfo;

            if (asyncDebugInfo != null)
            {
                _stateMachineMethodTable.Add(new StateMachineMethodRow
                {
                    MoveNextMethod = (uint)methodRid,
                    KickoffMethod  = (uint)GetMethodDefIndex(asyncDebugInfo.KickoffMethod)
                });

                SerializeAsyncMethodSteppingInfo(asyncDebugInfo, methodRid);
            }

            SerializeStateMachineLocalScopes(bodyOpt, methodRid);

            // delta doesn't need this information - we use information recorded by previous generation emit
            if (Context.ModuleBuilder.CommonCompilation.Options.EnableEditAndContinue && !IsFullMetadata)
            {
                SerializeEncMethodDebugInformation(bodyOpt, methodRid);
            }
        }
 public SynthesizedMethodBodyDecorator(IMethodBody methodBody)
 {
     this.methodBody = methodBody;
 }
 private void SerializeMethodDebugInfo(IMethodBody bodyOpt, int methodRid, int aggregateMethodRid, StandaloneSignatureHandle localSignatureHandleOpt, ref LocalVariableHandle lastLocalVariableHandle, ref LocalConstantHandle lastLocalConstantHandle)
 {
     if (bodyOpt == null)
     {
         _debugMetadataOpt.AddMethodDebugInformation(document: default, sequencePoints: default);
示例#59
0
        private static void SerializeDynamicLocalInfo(IMethodBody methodBody, ArrayBuilder <PooledBlobBuilder> customDebugInfo)
        {
            if (!methodBody.HasDynamicLocalVariables)
            {
                return; //There are no dynamic locals
            }

            var dynamicLocals = ArrayBuilder <ILocalDefinition> .GetInstance();

            foreach (ILocalDefinition local in methodBody.LocalVariables)
            {
                Debug.Assert(local.SlotIndex >= 0);
                if (local.IsDynamic)
                {
                    dynamicLocals.Add(local);
                }
            }

            foreach (var currentScope in methodBody.LocalScopes)
            {
                foreach (var localConstant in currentScope.Constants)
                {
                    Debug.Assert(localConstant.SlotIndex < 0);
                    if (localConstant.IsDynamic)
                    {
                        dynamicLocals.Add(localConstant);
                    }
                }
            }

            Debug.Assert(dynamicLocals.Any()); // There must be at least one dynamic local if this point is reached

            const int dynamicAttributeSize = 64;
            const int identifierSize       = 64;
            const int blobSize             = dynamicAttributeSize + 4 + 4 + identifierSize * 2;//DynamicAttribute: 64, DynamicAttributeLength: 4, SlotIndex: 4, IdentifierName: 128
            var       cmw = PooledBlobBuilder.GetInstance();

            cmw.WriteByte(CustomDebugInfoConstants.Version);
            cmw.WriteByte((byte)CustomDebugInfoKind.DynamicLocals);
            cmw.Align(4);
            // size = Version,Kind + size + cBuckets + (dynamicCount * sizeOf(Local Blob))
            cmw.WriteUInt32(4 + 4 + 4 + (uint)dynamicLocals.Count * blobSize);//Size of the Dynamic Block
            cmw.WriteUInt32((uint)dynamicLocals.Count);

            foreach (ILocalDefinition local in dynamicLocals)
            {
                if (local.Name.Length >= identifierSize)//Ignore and push empty information
                {
                    cmw.WriteBytes(0, blobSize);
                    continue;
                }

                var dynamicTransformFlags = local.DynamicTransformFlags;
                if (!dynamicTransformFlags.IsDefault && dynamicTransformFlags.Length <= dynamicAttributeSize)
                {
                    byte[] flag = new byte[dynamicAttributeSize];
                    for (int k = 0; k < dynamicTransformFlags.Length; k++)
                    {
                        if ((bool)dynamicTransformFlags[k].Value)
                        {
                            flag[k] = 1;
                        }
                    }
                    cmw.WriteBytes(flag);                                //Written Flag
                    cmw.WriteUInt32((uint)dynamicTransformFlags.Length); //Written Length
                }
                else
                {
                    cmw.WriteBytes(0, dynamicAttributeSize + 4); //Empty flag array and size.
                }

                var localIndex = local.SlotIndex;
                cmw.WriteUInt32((localIndex < 0) ? 0u : (uint)localIndex);

                char[] localName = new char[identifierSize];
                local.Name.CopyTo(0, localName, 0, local.Name.Length);
                cmw.WriteUTF16(localName);
            }

            dynamicLocals.Free();
            customDebugInfo.Add(cmw);
        }