예제 #1
0
        /// <inheritdoc />
        public MethodBody ReadMethodBody(MethodDefinition owner, MethodDefinitionRow row)
        {
            try
            {
                if (row.Body.CanRead)
                {
                    if (owner.IsIL)
                    {
                        var rawBody = CilRawMethodBody.FromReader(row.Body.CreateReader());
                        return(CilMethodBody.FromRawMethodBody(owner, rawBody));
                    }
                    else
                    {
                        // TODO: handle native method bodies.
                    }
                }
                else if (row.Body.IsBounded && row.Body.GetSegment() is CilRawMethodBody rawMethodBody)
                {
                    return(CilMethodBody.FromRawMethodBody(owner, rawMethodBody));
                }
            }
            catch when(!ThrowOnInvalidMethodBody)
            {
                return(null);
            }

            return(null);
        }
예제 #2
0
        private static void ReplaceBodyWithNativeCode(IPEImage image, CodeSegment body, bool is32bit)
        {
            // Adjust image flags appropriately.
            image.DotNetDirectory.Flags &= ~DotNetDirectoryFlags.ILOnly;

            if (is32bit)
            {
                image.MachineType            = MachineType.I386;
                image.PEKind                 = OptionalHeaderMagic.Pe32;
                image.DotNetDirectory.Flags |= DotNetDirectoryFlags.Bit32Required;
            }
            else
            {
                image.MachineType = MachineType.Amd64;
                image.PEKind      = OptionalHeaderMagic.Pe32Plus;
            }

            // Access metadata.
            var metadata      = image.DotNetDirectory.Metadata;
            var stringsStream = metadata.GetStream <StringsStream>();
            var tablesStream  = metadata.GetStream <TablesStream>();
            var typeTable     = tablesStream.GetTable <TypeDefinitionRow>();
            var methodTable   = tablesStream.GetTable <MethodDefinitionRow>();

            // Find the method to replace its body of.
            int index = -1;

            for (int i = 0; i < methodTable.Count && index == -1; i++)
            {
                if (stringsStream.GetStringByIndex(methodTable[i].Name) == "GetTheAnswer")
                {
                    index = i;
                }
            }

            // Replace body.
            var methodRow = methodTable[index];

            methodTable[index] = new MethodDefinitionRow(
                new SegmentReference(body),
                methodRow.ImplAttributes | MethodImplAttributes.Native | MethodImplAttributes.Unmanaged
                | MethodImplAttributes.PreserveSig,
                methodRow.Attributes | MethodAttributes.PInvokeImpl,
                methodRow.Name,
                methodRow.Signature,
                methodRow.ParameterList);

            // Move to <Module>
            var typeRow = typeTable[1];

            typeTable[1] = new TypeDefinitionRow(
                typeRow.Attributes,
                typeRow.Name,
                typeRow.Namespace,
                typeRow.Extends,
                typeRow.FieldList,
                (uint)(index + 2));
        }
예제 #3
0
        /// <summary>
        /// Creates a method definition from a method metadata row.
        /// </summary>
        /// <param name="parentModule">The module that contains the method.</param>
        /// <param name="token">The token to initialize the method for.</param>
        /// <param name="row">The metadata table row to base the method definition on.</param>
        public SerializedMethodDefinition(SerializedModuleDefinition parentModule, MetadataToken token, MethodDefinitionRow row)
            : base(token)
        {
            _parentModule = parentModule ?? throw new ArgumentNullException(nameof(parentModule));
            _row          = row;

            Attributes     = row.Attributes;
            ImplAttributes = row.ImplAttributes;
        }
예제 #4
0
        public void RowEnumerationTest()
        {
            var rawRow = new uint[] { 0x00002050, 0x0000, 0x0091, 0x017E, 0x0023, 0x0001 };
            var row    = new MethodDefinitionRow(
                new VirtualAddress(rawRow[0]),
                (MethodImplAttributes)rawRow[1],
                (MethodAttributes)rawRow[2],
                rawRow[3],
                rawRow[4],
                rawRow[5]);

            RowTestUtils.VerifyRowColumnEnumeration(rawRow, row);
        }
예제 #5
0
        /// <summary>
        /// Allocates metadata rows for the provided method definitions in the buffer.
        /// </summary>
        /// <param name="methods">The methods to define.</param>
        public void DefineMethods(IEnumerable <MethodDefinition> methods)
        {
            var table = Metadata.TablesStream.GetTable <MethodDefinitionRow>(TableIndex.Method);

            foreach (var method in methods)
            {
                // At this point, we might not have added all type defs/refs/specs yet, so we must delay the
                // serialization of the method body, as well as determining the parameter list.

                var row = new MethodDefinitionRow(
                    null,
                    method.ImplAttributes,
                    method.Attributes,
                    Metadata.StringsStream.GetStringIndex(method.Name),
                    Metadata.BlobStream.GetBlobIndex(this, method.Signature, DiagnosticBag),
                    0);

                var token = table.Add(row);
                _tokenMapping.Register(method, token);
            }
        }