Example #1
0
        /// <summary>
        /// Reads a raw <c>GenericParam</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 TryReadGenericParamRow(uint rid, out RawGenericParamRow row)
        {
            var table = GenericParamTable;

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

            reader.Position = (rid - 1) * (uint)table.TableInfo.RowSize;
            if (table.Column4 == null)
            {
                row = new RawGenericParamRow(
                    reader.Unsafe_ReadUInt16(),
                    reader.Unsafe_ReadUInt16(),
                    table.Column2.Unsafe_Read24(ref reader),
                    table.Column3.Unsafe_Read24(ref reader));
                return(true);
            }
            else
            {
                row = new RawGenericParamRow(
                    reader.Unsafe_ReadUInt16(),
                    reader.Unsafe_ReadUInt16(),
                    table.Column2.Unsafe_Read24(ref reader),
                    table.Column3.Unsafe_Read24(ref reader),
                    table.Column4.Unsafe_Read24(ref reader));
                return(true);
            }
        }
Example #2
0
 public int GetHashCode(RawGenericParamRow obj)
 {
     return((int)obj.Number +
            rol(obj.Flags, 3) +
            rol(obj.Owner, 7) +
            rol(obj.Name, 11) +
            rol(obj.Kind, 15));
 }
Example #3
0
 public bool Equals(RawGenericParamRow x, RawGenericParamRow y)
 {
     return(x.Number == y.Number &&
            x.Flags == y.Flags &&
            x.Owner == y.Owner &&
            x.Name == y.Name &&
            x.Kind == y.Kind);
 }
 void InitializeRawRow()
 {
     if (rawRow != null)
     {
         return;
     }
     rawRow = readerModule.TablesStream.ReadGenericParamRow(rid);
 }
Example #5
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 #6
0
 static uint ReadGenericParamColumnMethod(ref RawGenericParamRow row, int index) => row[index];