Example #1
0
 public int GetHashCode(RawMethodRow obj) =>
 (int)obj.RVA +
 rol(obj.ImplFlags, 3) +
 rol(obj.Flags, 7) +
 rol(obj.Name, 11) +
 rol(obj.Signature, 15) +
 rol(obj.ParamList, 19);
Example #2
0
        /// <summary>
        /// Reads a raw <c>Method</c> row or returns false if the row doesn't exist
        /// </summary>
        /// <param name="rid">Row ID</param>
        /// <param name="row">Row data</param>
        /// <returns></returns>
        public bool TryReadMethodRow(uint rid, out RawMethodRow row)
        {
            var table = MethodTable;

            if (table.IsInvalidRID(rid))
            {
                row = default;
                return(false);
            }
            var mrr = methodRowReader;

            if (mrr != null && mrr.TryReadRow(rid, out row))
            {
                return(true);
            }
            var reader = table.DataReader;

            reader.Position = (rid - 1) * (uint)table.TableInfo.RowSize;
            row             = new RawMethodRow(
                reader.Unsafe_ReadUInt32(),
                reader.Unsafe_ReadUInt16(),
                reader.Unsafe_ReadUInt16(),
                table.Column3.Unsafe_Read24(ref reader),
                table.Column4.Unsafe_Read24(ref reader),
                table.Column5.Unsafe_Read24(ref reader));
            return(true);
        }
Example #3
0
 public bool Equals(RawMethodRow x, RawMethodRow y) =>
 x.RVA == y.RVA &&
 x.ImplFlags == y.ImplFlags &&
 x.Flags == y.Flags &&
 x.Name == y.Name &&
 x.Signature == y.Signature &&
 x.ParamList == y.ParamList;
Example #4
0
 public DmdMethodDefMD(DmdEcma335MetadataReader reader, RawMethodRow row, uint rid, string name, DmdType declaringType, DmdType reflectedType) : base(rid, declaringType, reflectedType)
 {
     this.reader = reader ?? throw new ArgumentNullException(nameof(reader));
     MethodImplementationFlags = (DmdMethodImplAttributes)row.ImplFlags;
     Attributes      = (DmdMethodAttributes)row.Flags;
     Name            = name ?? throw new ArgumentNullException(nameof(name));
     methodSignature = reader.ReadMethodSignature(row.Signature, DeclaringType.GetGenericArguments(), GetGenericArguments(), isProperty: false);
 }
Example #5
0
 void InitializeRawRow()
 {
     if (rawRow != null)
     {
         return;
     }
     rawRow = readerModule.TablesStream.ReadMethodRow(rid);
 }
Example #6
0
        public static void Erase(NativeModuleWriter writer, ModuleDefMD module)
        {
            if (writer == null || module == null)
            {
                return;
            }
            List <Tuple <uint, uint, byte[]> > sections = new List <Tuple <uint, uint, byte[]> >();
            MemoryStream s = new MemoryStream();

            foreach (NativeModuleWriter.OrigSection origSect in writer.OrigSections)
            {
                var oldChunk = origSect.Chunk;
                ImageSectionHeader sectHdr = origSect.PESection;
                s.SetLength(0L);
                oldChunk.WriteTo(new BinaryWriter(s));
                byte[] buf      = s.ToArray();
                var    newChunk = new BinaryReaderChunk(MemoryImageStream.Create(buf), oldChunk.GetVirtualSize());
                newChunk.SetOffset(oldChunk.FileOffset, oldChunk.RVA);
                origSect.Chunk = newChunk;
                sections.Add(Tuple.Create <uint, uint, byte[]>(sectHdr.PointerToRawData, sectHdr.PointerToRawData + sectHdr.SizeOfRawData, buf));
            }

            var  md  = module.MetaData;
            uint row = md.TablesStream.MethodTable.Rows;

            for (uint i = 1u; i <= row; i += 1u)
            {
                RawMethodRow method = md.TablesStream.ReadMethodRow(i);

                if ((method.ImplFlags & 3) == 0)
                {
                    Erase(sections, (uint)md.PEImage.ToFileOffset((RVA)method.RVA));
                }
            }
            ImageDataDirectory res = md.ImageCor20Header.Resources;

            if (res.Size > 0u)
            {
                Erase(sections, (uint)res.StartOffset, res.Size);
            }
            Erase(sections, md.ImageCor20Header);
            Erase(sections, md.MetaDataHeader);// md.MetadataHeader);
            foreach (DotNetStream stream in md.AllStreams)
            {
                Erase(sections, stream);
            }
        }
Example #7
0
		void InjectNativeCode(object sender, ModuleWriterEventArgs e) {
			var writer = (ModuleWriterBase)sender;
			if (e.Event == ModuleWriterEvent.MDEndWriteMethodBodies) {
				for (int n = 0; n < nativeCodes.Count; n++)
					nativeCodes[n] = new Tuple<MethodDef, byte[], MethodBody>(
						nativeCodes[n].Item1,
						nativeCodes[n].Item2,
						writer.MethodBodies.Add(new MethodBody(nativeCodes[n].Item2)));
			}
			else if (e.Event == ModuleWriterEvent.EndCalculateRvasAndFileOffsets) {
				foreach (var native in nativeCodes) {
					uint rid = writer.Metadata.GetRid(native.Item1);
          RawMethodRow methodRow = writer.Metadata.TablesHeap.MethodTable[rid];
          writer.Metadata.TablesHeap.MethodTable[rid] = new RawMethodRow(
            (uint)native.Item3.RVA,
            methodRow.ImplFlags,
            methodRow.Flags,
            methodRow.Name,
            methodRow.Signature,
            methodRow.ParamList);
				}
			}
		}
Example #8
0
        /// <summary>
        /// Patches all columns and blob signatures that reference a moved TypeDef so they reference the new TypeRef
        /// </summary>
        void PatchTypeTokenReferences(TypeDef nonNestedEditedType)
        {
            if (remappedTypeTokens.Count == 0)
            {
                return;
            }

            // NOTE: We don't patch the following:
            //	- Method bodies
            //	- All MemberRefs referenced by method bodies
            //	- StandAloneSig.Signature. It's only used by method bodies
            //	- MethodSpec.Instantiation. It's only used by method bodies
            //	- Custom attribute blobs. Could reference the edited type but not likely to cause a problem.
            //	- Marshal blobs. Could reference the edited type but not likely to cause a problem.
            //	  The MD writer doesn't write the FieldMarshal table.

            var tablesHeap = mdEditor.TablesHeap;

            var typeSigDict     = new Dictionary <uint, uint>();
            var callConvSigDict = new Dictionary <uint, uint>();

            MDTable    table;
            byte *     p;
            int        rowSize;
            ColumnInfo column, column2;
            uint       i, codedToken, newToken, sig, newSig, rid;
            MDToken    token;

            // Patch the TypeDef table
            {
                table   = mdEditor.RealMetadata.TablesStream.TypeDefTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[3];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                    {
                        var row = tablesHeap.TypeDefTable.Get(i + 1);
                        row = new RawTypeDefRow(row.Flags, row.Name, row.Namespace, CodedToken.TypeDefOrRef.Encode(newToken), row.FieldList, row.MethodList);
                        tablesHeap.TypeDefTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the Field table
            {
                table   = mdEditor.RealMetadata.TablesStream.FieldTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[2];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    sig    = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    newSig = PatchCallingConventionSignature(callConvSigDict, sig);
                    if (newSig != sig)
                    {
                        var row = tablesHeap.FieldTable.Get(i + 1);
                        row = new RawFieldRow(row.Flags, row.Name, newSig);
                        tablesHeap.FieldTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the Method table
            {
                table   = mdEditor.RealMetadata.TablesStream.MethodTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[4];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    sig    = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    newSig = PatchCallingConventionSignature(callConvSigDict, sig);
                    if (newSig != sig)
                    {
                        var row = tablesHeap.MethodTable.Get(i + 1);
                        row = new RawMethodRow(row.RVA, row.ImplFlags, row.Flags, row.Name, newSig, row.ParamList);
                        tablesHeap.MethodTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the InterfaceImpl table
            {
                table   = mdEditor.RealMetadata.TablesStream.InterfaceImplTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[1];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                    {
                        var row = tablesHeap.InterfaceImplTable.Get(i + 1);
                        row = new RawInterfaceImplRow(row.Class, CodedToken.TypeDefOrRef.Encode(newToken));
                        tablesHeap.InterfaceImplTable.Set(i + 1, ref row);
                    }
                }
            }

            //TODO: PERF: If needed, this table could mostly be skipped. We only need to update refs from:
            //			CustomAttribute.Type, MethodImpl.MethodBody, MethodImpl.MethodDeclaration
            //		CustomAttribute.Type almost never references the edited type, and if it does, the
            //		edited type, or any of its nested types, is an attribute. Quick test: this block
            //		took ~25% of the total time (patch file, write new MD, test file was dnSpy.exe = 3.3MB).
            // Patch the MemberRef table
            {
                table   = mdEditor.RealMetadata.TablesStream.MemberRefTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[0];
                column2 = table.Columns[2];
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.MemberRefParent.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    rid = i + 1;
                    RawMemberRefRow row;
                    switch (token.Table)
                    {
                    case Table.TypeRef:
                    case Table.TypeDef:
                    case Table.TypeSpec:
                        if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                        {
                            row = tablesHeap.MemberRefTable.Get(rid);
                            row = new RawMemberRefRow(CodedToken.MemberRefParent.Encode(newToken), row.Name, row.Signature);
                            tablesHeap.MemberRefTable.Set(rid, ref row);
                        }
                        break;

                    case Table.ModuleRef:
                        if (nonNestedEditedType.IsGlobalModuleType && CheckResolutionScopeIsSameModule(token, nonNestedEditedType.Module))
                        {
                            if (remappedTypeTokens.TryGetValue(nonNestedEditedType.MDToken.Raw, out newToken))
                            {
                                row = tablesHeap.MemberRefTable.Get(rid);
                                row = new RawMemberRefRow(CodedToken.MemberRefParent.Encode(newToken), row.Name, row.Signature);
                                tablesHeap.MemberRefTable.Set(rid, ref row);
                            }
                        }
                        break;

                    case Table.Method:
                        break;

                    default:
                        Debug.Fail("Impossible");
                        break;
                    }

                    sig    = column2.Size == 2 ? *(ushort *)(p + column2.Offset) : *(uint *)(p + column2.Offset);
                    newSig = PatchCallingConventionSignature(callConvSigDict, sig);
                    if (sig != newSig)
                    {
                        row = tablesHeap.MemberRefTable.Get(rid);
                        row = new RawMemberRefRow(row.Class, row.Name, newSig);
                        tablesHeap.MemberRefTable.Set(rid, ref row);
                    }
                }
            }

            // Patch the Event table
            {
                table   = mdEditor.RealMetadata.TablesStream.EventTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[2];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                    {
                        var row = tablesHeap.EventTable.Get(i + 1);
                        row = new RawEventRow(row.EventFlags, row.Name, CodedToken.TypeDefOrRef.Encode(newToken));
                        tablesHeap.EventTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the Property table
            {
                table   = mdEditor.RealMetadata.TablesStream.PropertyTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[2];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    sig    = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    newSig = PatchCallingConventionSignature(callConvSigDict, sig);
                    if (newSig != sig)
                    {
                        var row = tablesHeap.PropertyTable.Get(i + 1);
                        row = new RawPropertyRow(row.PropFlags, row.Name, newSig);
                        tablesHeap.PropertyTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the TypeSpec table
            {
                table   = mdEditor.RealMetadata.TablesStream.TypeSpecTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[0];
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    sig    = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    newSig = PatchTypeSignature(typeSigDict, sig);
                    if (newSig != sig)
                    {
                        var row = new RawTypeSpecRow(newSig);
                        tablesHeap.TypeSpecTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the GenericParam table
            if (mdEditor.RealMetadata.TablesStream.GenericParamTable.Columns.Count == 5)
            {
                table   = mdEditor.RealMetadata.TablesStream.GenericParamTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[4];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                    {
                        var row = tablesHeap.GenericParamTable.Get(i + 1);
                        row = new RawGenericParamRow(row.Number, row.Flags, row.Owner, row.Name, CodedToken.TypeDefOrRef.Encode(newToken));
                        tablesHeap.GenericParamTable.Set(i + 1, ref row);
                    }
                }
            }

            // Patch the GenericParamConstraint table
            {
                table   = mdEditor.RealMetadata.TablesStream.GenericParamConstraintTable;
                p       = peFile + (int)table.StartOffset;
                rowSize = (int)table.RowSize;
                column  = table.Columns[1];
                p      += column.Offset;
                for (i = 0; i < table.Rows; i++, p += rowSize)
                {
                    codedToken = column.Size == 2 ? *(ushort *)p : *(uint *)p;
                    if (!CodedToken.TypeDefOrRef.Decode(codedToken, out token))
                    {
                        continue;
                    }
                    if (remappedTypeTokens.TryGetValue(token.Raw, out newToken))
                    {
                        var row = tablesHeap.GenericParamConstraintTable.Get(i + 1);
                        row = new RawGenericParamConstraintRow(row.Owner, CodedToken.TypeDefOrRef.Encode(newToken));
                        tablesHeap.GenericParamConstraintTable.Set(i + 1, ref row);
                    }
                }
            }
        }
Example #9
0
        /// <inheritdoc/>
        protected override void AllocateMemberDefRids()
        {
            int       numTypes        = allTypeDefs.Count;
            int       typeNum         = 0;
            int       notifyNum       = 0;
            const int numNotifyEvents = 5; // AllocateMemberDefRids0 - AllocateMemberDefRids4
            int       notifyAfter     = numTypes / numNotifyEvents;

            uint fieldListRid = 1, methodListRid = 1;
            uint eventListRid = 1, propertyListRid = 1;
            uint paramListRid = 1;

            foreach (var type in allTypeDefs)
            {
                if (typeNum++ == notifyAfter && notifyNum < numNotifyEvents)
                {
                    Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids0 + notifyNum++);
                    notifyAfter += numTypes / numNotifyEvents;
                }

                if (type == null)
                {
                    continue;
                }
                uint typeRid = GetRid(type);
                var  typeRow = tablesHeap.TypeDefTable[typeRid];
                typeRow.FieldList  = fieldListRid;
                typeRow.MethodList = methodListRid;

                foreach (var field in type.Fields)
                {
                    if (field == null)
                    {
                        continue;
                    }
                    uint rid = fieldListRid++;
                    if (rid != tablesHeap.FieldTable.Create(new RawFieldRow()))
                    {
                        throw new ModuleWriterException("Invalid field rid");
                    }
                    fieldDefInfos.Add(field, rid);
                }

                foreach (var method in type.Methods)
                {
                    if (method == null)
                    {
                        continue;
                    }
                    uint rid = methodListRid++;
                    var  row = new RawMethodRow(0, 0, 0, 0, 0, paramListRid);
                    if (rid != tablesHeap.MethodTable.Create(row))
                    {
                        throw new ModuleWriterException("Invalid method rid");
                    }
                    methodDefInfos.Add(method, rid);
                    foreach (var pd in Sort(method.ParamDefs))
                    {
                        if (pd == null)
                        {
                            continue;
                        }
                        uint pdRid = paramListRid++;
                        if (pdRid != tablesHeap.ParamTable.Create(new RawParamRow()))
                        {
                            throw new ModuleWriterException("Invalid param rid");
                        }
                        paramDefInfos.Add(pd, pdRid);
                    }
                }

                if (!IsEmpty(type.Events))
                {
                    uint eventMapRid = tablesHeap.EventMapTable.Create(new RawEventMapRow(typeRid, eventListRid));
                    eventMapInfos.Add(type, eventMapRid);
                    foreach (var evt in type.Events)
                    {
                        if (evt == null)
                        {
                            continue;
                        }
                        uint rid = eventListRid++;
                        if (rid != tablesHeap.EventTable.Create(new RawEventRow()))
                        {
                            throw new ModuleWriterException("Invalid event rid");
                        }
                        eventDefInfos.Add(evt, rid);
                    }
                }

                if (!IsEmpty(type.Properties))
                {
                    uint propertyMapRid = tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(typeRid, propertyListRid));
                    propertyMapInfos.Add(type, propertyMapRid);
                    foreach (var prop in type.Properties)
                    {
                        if (prop == null)
                        {
                            continue;
                        }
                        uint rid = propertyListRid++;
                        if (rid != tablesHeap.PropertyTable.Create(new RawPropertyRow()))
                        {
                            throw new ModuleWriterException("Invalid property rid");
                        }
                        propertyDefInfos.Add(prop, rid);
                    }
                }
            }
            while (notifyNum < numNotifyEvents)
            {
                Listener.OnMetaDataEvent(this, MetaDataEvent.AllocateMemberDefRids0 + notifyNum++);
            }
        }
        /// <inheritdoc/>
        protected override void AllocateMemberDefRids()
        {
            uint fieldListRid = 1, methodListRid = 1;
            uint eventListRid = 1, propertyListRid = 1;
            uint paramListRid = 1;

            foreach (var type in allTypeDefs)
            {
                if (type == null)
                {
                    continue;
                }
                uint typeRid = GetRid(type);
                var  typeRow = tablesHeap.TypeDefTable[typeRid];
                typeRow.FieldList  = fieldListRid;
                typeRow.MethodList = methodListRid;

                foreach (var field in type.Fields)
                {
                    if (field == null)
                    {
                        continue;
                    }
                    uint rid = fieldListRid++;
                    if (rid != tablesHeap.FieldTable.Create(new RawFieldRow()))
                    {
                        throw new ModuleWriterException("Invalid field rid");
                    }
                    fieldDefInfos.Add(field, rid);
                }

                foreach (var method in type.Methods)
                {
                    if (method == null)
                    {
                        continue;
                    }
                    uint rid = methodListRid++;
                    var  row = new RawMethodRow(0, 0, 0, 0, 0, paramListRid);
                    if (rid != tablesHeap.MethodTable.Create(row))
                    {
                        throw new ModuleWriterException("Invalid method rid");
                    }
                    methodDefInfos.Add(method, rid);
                    foreach (var pd in Sort(method.ParamDefs))
                    {
                        if (pd == null)
                        {
                            continue;
                        }
                        uint pdRid = paramListRid++;
                        if (pdRid != tablesHeap.ParamTable.Create(new RawParamRow()))
                        {
                            throw new ModuleWriterException("Invalid param rid");
                        }
                        paramDefInfos.Add(pd, pdRid);
                    }
                }

                if (!IsEmpty(type.Events))
                {
                    uint eventMapRid = tablesHeap.EventMapTable.Create(new RawEventMapRow(typeRid, eventListRid));
                    eventMapInfos.Add(type, eventMapRid);
                    foreach (var evt in type.Events)
                    {
                        if (evt == null)
                        {
                            continue;
                        }
                        uint rid = eventListRid++;
                        if (rid != tablesHeap.EventTable.Create(new RawEventRow()))
                        {
                            throw new ModuleWriterException("Invalid event rid");
                        }
                        eventDefInfos.Add(evt, rid);
                    }
                }

                if (!IsEmpty(type.Properties))
                {
                    uint propertyMapRid = tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(typeRid, propertyListRid));
                    propertyMapInfos.Add(type, propertyMapRid);
                    foreach (var prop in type.Properties)
                    {
                        if (prop == null)
                        {
                            continue;
                        }
                        uint rid = propertyListRid++;
                        if (rid != tablesHeap.PropertyTable.Create(new RawPropertyRow()))
                        {
                            throw new ModuleWriterException("Invalid property rid");
                        }
                        propertyDefInfos.Add(prop, rid);
                    }
                }
            }
        }
Example #11
0
 static uint ReadMethodColumnMethod(ref RawMethodRow row, int index) => row[index];
        /// <inheritdoc/>
        protected override void AllocateMemberDefRids()
        {
            int       numTypes        = allTypeDefs.Length;
            int       typeNum         = 0;
            int       notifyNum       = 0;
            const int numNotifyEvents = 5;
            int       notifyAfter     = numTypes / numNotifyEvents;

            uint fieldListRid = 1, methodListRid = 1;
            uint eventListRid = 1, propertyListRid = 1;
            uint paramListRid = 1;
            int  count;

            foreach (var type in allTypeDefs)
            {
                if (typeNum++ == notifyAfter && notifyNum < numNotifyEvents)
                {
                    RaiseProgress(Writer.MetadataEvent.AllocateMemberDefRids, (double)typeNum / numTypes);
                    notifyNum++;
                    notifyAfter = (int)((double)numTypes / numNotifyEvents * (notifyNum + 1));
                }

                if (type == null)
                {
                    continue;
                }
                uint typeRid = GetRid(type);
                var  typeRow = tablesHeap.TypeDefTable[typeRid];
                typeRow = new RawTypeDefRow(typeRow.Flags, typeRow.Name, typeRow.Namespace, typeRow.Extends, fieldListRid, methodListRid);
                tablesHeap.TypeDefTable[typeRid] = typeRow;

                var fields = type.Fields;
                count = fields.Count;
                for (int i = 0; i < count; i++)
                {
                    var field = fields[i];
                    if (field == null)
                    {
                        continue;
                    }
                    uint rid = fieldListRid++;
                    if (rid != tablesHeap.FieldTable.Create(new RawFieldRow()))
                    {
                        throw new ModuleWriterException("Invalid field rid");
                    }
                    fieldDefInfos.Add(field, rid);
                }

                var methods = type.Methods;
                count = methods.Count;
                for (int i = 0; i < count; i++)
                {
                    var method = methods[i];
                    if (method == null)
                    {
                        continue;
                    }
                    uint rid = methodListRid++;
                    var  row = new RawMethodRow(0, 0, 0, 0, 0, paramListRid);
                    if (rid != tablesHeap.MethodTable.Create(row))
                    {
                        throw new ModuleWriterException("Invalid method rid");
                    }
                    methodDefInfos.Add(method, rid);
                    foreach (var pd in Sort(method.ParamDefs))
                    {
                        if (pd == null)
                        {
                            continue;
                        }
                        uint pdRid = paramListRid++;
                        if (pdRid != tablesHeap.ParamTable.Create(new RawParamRow()))
                        {
                            throw new ModuleWriterException("Invalid param rid");
                        }
                        paramDefInfos.Add(pd, pdRid);
                    }
                }

                if (!IsEmpty(type.Events))
                {
                    uint eventMapRid = tablesHeap.EventMapTable.Create(new RawEventMapRow(typeRid, eventListRid));
                    eventMapInfos.Add(type, eventMapRid);
                    var events = type.Events;
                    count = events.Count;
                    for (int i = 0; i < count; i++)
                    {
                        var evt = events[i];
                        if (evt == null)
                        {
                            continue;
                        }
                        uint rid = eventListRid++;
                        if (rid != tablesHeap.EventTable.Create(new RawEventRow()))
                        {
                            throw new ModuleWriterException("Invalid event rid");
                        }
                        eventDefInfos.Add(evt, rid);
                    }
                }

                if (!IsEmpty(type.Properties))
                {
                    uint propertyMapRid = tablesHeap.PropertyMapTable.Create(new RawPropertyMapRow(typeRid, propertyListRid));
                    propertyMapInfos.Add(type, propertyMapRid);
                    var properties = type.Properties;
                    count = properties.Count;
                    for (int i = 0; i < count; i++)
                    {
                        var prop = properties[i];
                        if (prop == null)
                        {
                            continue;
                        }
                        uint rid = propertyListRid++;
                        if (rid != tablesHeap.PropertyTable.Create(new RawPropertyRow()))
                        {
                            throw new ModuleWriterException("Invalid property rid");
                        }
                        propertyDefInfos.Add(prop, rid);
                    }
                }
            }
        }
Example #13
0
        void CreateSection(ModuleWriterBase writer)
        {
            // move some PE parts to separate section to prevent it from being hashed
            var  peSection = new PESection("", 0x60000020);
            bool moved     = false;
            uint alignment;

            if (writer.StrongNameSignature != null)
            {
                alignment = writer.TextSection.Remove(writer.StrongNameSignature).Value;
                peSection.Add(writer.StrongNameSignature, alignment);
                moved = true;
            }
            var managedWriter = writer as ModuleWriter;

            if (managedWriter != null)
            {
                if (managedWriter.ImportAddressTable != null)
                {
                    alignment = writer.TextSection.Remove(managedWriter.ImportAddressTable).Value;
                    peSection.Add(managedWriter.ImportAddressTable, alignment);
                    moved = true;
                }
                if (managedWriter.StartupStub != null)
                {
                    alignment = writer.TextSection.Remove(managedWriter.StartupStub).Value;
                    peSection.Add(managedWriter.StartupStub, alignment);
                    moved = true;
                }
            }
            if (moved)
            {
                writer.Sections.AddBeforeReloc(peSection);
            }

            // create section
            var nameBuffer = new byte[8];

            nameBuffer[0] = (byte)(name1 >> 0);
            nameBuffer[1] = (byte)(name1 >> 8);
            nameBuffer[2] = (byte)(name1 >> 16);
            nameBuffer[3] = (byte)(name1 >> 24);
            nameBuffer[4] = (byte)(name2 >> 0);
            nameBuffer[5] = (byte)(name2 >> 8);
            nameBuffer[6] = (byte)(name2 >> 16);
            nameBuffer[7] = (byte)(name2 >> 24);
            var newSection = new PESection(Encoding.ASCII.GetString(nameBuffer), 0xE0000040);

            writer.Sections.InsertBeforeReloc(random.NextInt32(writer.Sections.Count), newSection);

            // random padding at beginning to prevent revealing hash key
            newSection.Add(new ByteArrayChunk(random.NextBytes(0x10)), 0x10);

            // create index
            var bodyIndex = new JITBodyIndex(methods.Select(method => writer.Metadata.GetToken(method).Raw));

            newSection.Add(bodyIndex, 0x10);

            // save methods
            foreach (MethodDef method in methods.WithProgress(context.Logger))
            {
                if (!method.HasBody)
                {
                    continue;
                }

                MDToken token = writer.Metadata.GetToken(method);

                var jitBody    = new JITMethodBody();
                var bodyWriter = new JITMethodBodyWriter(writer.Metadata, method.Body, jitBody, random.NextUInt32(), writer.Metadata.KeepOldMaxStack || method.Body.KeepOldMaxStack);
                bodyWriter.Write();
                jitBody.Serialize(token.Raw, key, fieldLayout);
                bodyIndex.Add(token.Raw, jitBody);

                method.Body = NopBody;
                RawMethodRow methodRow = writer.Metadata.TablesHeap.MethodTable[token.Rid];
                writer.Metadata.TablesHeap.MethodTable[token.Rid] = new RawMethodRow(
                    methodRow.RVA,
                    (ushort)(methodRow.ImplFlags | (ushort)MethodImplAttributes.NoInlining),
                    methodRow.Flags,
                    methodRow.Name,
                    methodRow.Signature,
                    methodRow.ParamList);

                context.CheckCancellation();
            }
            bodyIndex.PopulateSection(newSection);

            // padding to prevent bad size due to shift division
            newSection.Add(new ByteArrayChunk(new byte[4]), 4);
        }