예제 #1
0
        public void RowEnumerationTest()
        {
            var rawRow = new uint[] { 0, 0x0001, 0x0000, 0x0000, 0x0001, 0x0001 };
            var row    = new TypeDefinitionRow((TypeAttributes)rawRow[0], rawRow[1], rawRow[2],
                                               rawRow[3], rawRow[4], rawRow[5]);

            RowTestUtils.VerifyRowColumnEnumeration(rawRow, row);
        }
예제 #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 type definition from a type metadata row.
        /// </summary>
        /// <param name="parentModule"></param>
        /// <param name="token">The token to initialize the type for.</param>
        /// <param name="row">The metadata table row to base the type definition on.</param>
        public SerializedTypeDefinition(SerializedModuleDefinition parentModule, MetadataToken token, TypeDefinitionRow row)
            : base(token)
        {
            _parentModule = parentModule ?? throw new ArgumentNullException(nameof(parentModule));
            _row          = row;
            Attributes    = row.Attributes;

            ((IOwnedCollectionElement <ModuleDefinition>) this).Owner = parentModule;
        }
예제 #4
0
        /// <summary>
        /// Allocates metadata rows for the provided type definitions in the buffer.
        /// </summary>
        /// <param name="types">The types to define.</param>
        /// <remarks>
        /// This method does not define any member defined in the type, except for nested types.
        /// </remarks>
        public void DefineTypes(IEnumerable <TypeDefinition> types)
        {
            var typeDefTable     = Metadata.TablesStream.GetTable <TypeDefinitionRow>(TableIndex.TypeDef);
            var nestedClassTable = Metadata.TablesStream.GetSortedTable <TypeDefinition, NestedClassRow>(TableIndex.NestedClass);

            foreach (var type in types)
            {
                // At this point, we might not have added all type defs/refs/specs yet, so we cannot determine
                // the extends column, nor determine the field and method lists of this type.

                var row = new TypeDefinitionRow(
                    type.Attributes,
                    Metadata.StringsStream.GetStringIndex(type.Name),
                    Metadata.StringsStream.GetStringIndex(type.Namespace),
                    0,
                    0,
                    0);

                var token = typeDefTable.Add(row);
                _tokenMapping.Register(type, token);

                if (type.IsNested)
                {
                    // As per the ECMA-335; nested types should always follow their enclosing types in the TypeDef table.
                    // Proper type def collections that are passed onto this function therefore should have been added
                    // already to the buffer. If not, we have an invalid ordering of types.

                    var enclosingTypeToken = GetTypeDefinitionToken(type.DeclaringType);
                    if (enclosingTypeToken.Rid == 0)
                    {
                        DiagnosticBag.RegisterException(new MetadataBuilderException(
                                                            $"Nested type {type.SafeToString()} is added before its enclosing class {type.DeclaringType.SafeToString()}."));
                    }

                    var nestedClassRow = new NestedClassRow(
                        token.Rid,
                        enclosingTypeToken.Rid);

                    nestedClassTable.Add(type, nestedClassRow);
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Finalizes all type definitions added in the buffer.
        /// </summary>
        public void FinalizeTypes()
        {
            var tablesStream = Metadata.TablesStream;
            var typeDefTable = tablesStream.GetTable <TypeDefinitionRow>(TableIndex.TypeDef);

            bool fieldPtrRequired    = false;
            bool methodPtrRequired   = false;
            bool paramPtrRequired    = false;
            bool propertyPtrRequired = false;
            bool eventPtrRequired    = false;

            uint fieldList    = 1;
            uint methodList   = 1;
            uint propertyList = 1;
            uint eventList    = 1;

            for (uint rid = 1; rid <= typeDefTable.Count; rid++)
            {
                var typeToken = new MetadataToken(TableIndex.TypeDef, rid);
                var type      = _tokenMapping.GetTypeByToken(typeToken);

                // Update extends, field list and method list columns.
                var typeRow = typeDefTable[rid];
                typeDefTable[rid] = new TypeDefinitionRow(
                    typeRow.Attributes,
                    typeRow.Name,
                    typeRow.Namespace,
                    GetTypeDefOrRefIndex(type.BaseType),
                    fieldList,
                    methodList);

                // Finalize fields and methods.
                FinalizeFieldsInType(type, ref fieldPtrRequired);
                AddMethodPointers(type, ref methodPtrRequired);
                FinalizePropertiesInType(type, rid, ref propertyList, ref propertyPtrRequired);
                FinalizeEventsInType(type, rid, ref eventList, ref eventPtrRequired);

                // Move to next ember lists.
                fieldList  += (uint)type.Fields.Count;
                methodList += (uint)type.Methods.Count;

                // Add remaining metadata:
                AddCustomAttributes(typeToken, type);
                AddSecurityDeclarations(typeToken, type);
                DefineInterfaces(typeToken, type.Interfaces);
                AddMethodImplementations(typeToken, type.MethodImplementations);
                DefineGenericParameters(typeToken, type);
                AddClassLayout(typeToken, type.ClassLayout);
            }

            FinalizeMethods(ref paramPtrRequired);

            // Check if any of the redirection tables can be removed.
            if (!fieldPtrRequired)
            {
                tablesStream.GetTable <FieldPointerRow>(TableIndex.FieldPtr).Clear();
            }
            if (!methodPtrRequired)
            {
                tablesStream.GetTable <MethodPointerRow>(TableIndex.MethodPtr).Clear();
            }
            if (!paramPtrRequired)
            {
                tablesStream.GetTable <ParameterPointerRow>(TableIndex.ParamPtr).Clear();
            }
            if (!propertyPtrRequired)
            {
                tablesStream.GetTable <PropertyPointerRow>(TableIndex.PropertyPtr).Clear();
            }
            if (!eventPtrRequired)
            {
                tablesStream.GetTable <EventPointerRow>(TableIndex.EventPtr).Clear();
            }
        }