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); }
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)); }
/// <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; }
/// <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); } } }
/// <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(); } }