Ejemplo n.º 1
0
        internal void GetSystemTableRows(out ulong mask, uint[] tables)
        {
            if (tables.Length != 0x40)
            {
                throw new InvalidOperationException();
            }
            var   tablesMask = GetValidMask();
            ulong bit        = 1;

            mask = 0;
            for (int i = 0; i < 0x40; i++, bit <<= 1)
            {
                var table = (Table)i;
                if (DotNetTableSizes.IsSystemTable(table))
                {
                    if ((tablesMask & bit) != 0)
                    {
                        tables[i] = (uint)Tables[i].Rows;
                        mask     |= bit;
                    }
                    else
                    {
                        tables[i] = 0;
                    }
                }
                else
                {
                    tables[i] = 0;
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Calculates the length. This will set all MD tables to read-only.
        /// </summary>
        public void CalculateLength()
        {
            if (length != 0)
            {
                return;
            }
            SetReadOnly();

            majorVersion = options.MajorVersion ?? 2;
            minorVersion = options.MinorVersion ?? 0;

            if (((majorVersion << 8) | minorVersion) <= 0x100)
            {
                if (!GenericParamTable.IsEmpty || !MethodSpecTable.IsEmpty || !GenericParamConstraintTable.IsEmpty)
                {
                    throw new ModuleWriterException("Tables heap version <= v1.0 but generic tables are not empty");
                }
            }

            var dnTableSizes = new DotNetTableSizes();
            var tableInfos   = dnTableSizes.CreateTables(majorVersion, minorVersion);
            var rowCounts    = GetRowCounts();

            dnTableSizes.InitializeSizes(bigStrings, bigGuid, bigBlob, systemTables ?? rowCounts, rowCounts);
            for (int i = 0; i < Tables.Length; i++)
            {
                Tables[i].TableInfo = tableInfos[i];
            }

            length = 24;
            foreach (var mdt in Tables)
            {
                if (mdt.IsEmpty)
                {
                    continue;
                }
                length += (uint)(4 + mdt.TableInfo.RowSize * mdt.Rows);
            }
            if (options.ExtraData.HasValue)
            {
                length += 4;
            }
        }
Ejemplo n.º 3
0
        public unsafe override void Write(MDWriter mdWriter, MDWriterStream stream, byte[] tempBuffer)
        {
            var tblStream = mdWriter.MetadataEditor.RealMetadata.TablesStream;

            stream.Write(tblStream.Reserved1);
            stream.Write((byte)(tblStream.Version >> 8));
            stream.Write((byte)tblStream.Version);
            stream.Write((byte)mdStreamFlags);
            stream.Write((byte)1);
            stream.Write(GetValidMask(tablesHeap));
            stream.Write(GetSortedMask(tablesHeap, tblStream.SortedMask));
            var rowCounts = new uint[tablesHeap.TableInfos.Length];
            var infos     = tablesHeap.TableInfos;

            for (int i = 0; i < infos.Length; i++)
            {
                if (tablesToIgnore[i])
                {
                    continue;
                }
                var info = infos[i];
                if (info != null && !info.IsEmpty)
                {
                    rowCounts[i] = info.Rows;
                    stream.Write(info.Rows);
                }
            }

            var dnTableSizes = new DotNetTableSizes();
            var tableInfos   = dnTableSizes.CreateTables((byte)(tblStream.Version >> 8), (byte)tblStream.Version);

            dnTableSizes.InitializeSizes((mdStreamFlags & MDStreamFlags.BigStrings) != 0,
                                         (mdStreamFlags & MDStreamFlags.BigGUID) != 0,
                                         (mdStreamFlags & MDStreamFlags.BigBlob) != 0,
                                         rowCounts, rowCounts);

            long totalSize = 0;

            for (int i = 0; i < infos.Length; i++)
            {
                if (tablesToIgnore[i])
                {
                    continue;
                }
                var info = infos[i];
                if (info != null && !info.IsEmpty)
                {
                    totalSize += (long)info.Rows * tableInfos[i].RowSize;
                }
            }

            // NOTE: We don't write method bodies or field data, the compiler shouldn't
            // read Method.RVA. We also don't write the FieldRVA table.

            // PERF: Write to a temp buffer followed by a call to stream.Write(byte[]). It's faster
            // than calling stream.Write() for every row + column.

            var tablesPos       = stream.Position;
            int tempBufferIndex = 0;

            for (int i = 0; i < infos.Length; i++)
            {
                if (tablesToIgnore[i])
                {
                    continue;
                }
                var info = infos[i];
                if (info == null || info.IsEmpty)
                {
                    continue;
                }

                var tableWriter = TableWriter.Create(info);
                var mdTable     = info.MDTable;

                var  tbl             = tableInfos[i];
                var  columns         = tbl.Columns;
                var  rows            = tableWriter.Rows;
                uint currentRowIndex = 0;
                var  rowSize         = (uint)tbl.RowSize;
                Debug.Assert(tempBuffer.Length >= rowSize, "Temp buffer is too small");

                // If there are no changes in the original metadata or layout, just copy everything
                uint unmodifiedRows = tableWriter.FirstModifiedRowId - 1;
                if (unmodifiedRows > 0 && Equals(mdTable.TableInfo, tbl))
                {
                    if (tempBufferIndex > 0)
                    {
                        stream.Write(tempBuffer, 0, tempBufferIndex);
                        tempBufferIndex = 0;
                    }

                    stream.Write((byte *)mdWriter.ModuleData.Pointer + (int)mdTable.StartOffset, (int)(unmodifiedRows * mdTable.RowSize));

                    Debug.Assert(unmodifiedRows <= rows);
                    rows            -= unmodifiedRows;
                    currentRowIndex += unmodifiedRows;
                }

                while (rows > 0)
                {
                    int  bytesLeft = tempBuffer.Length - tempBufferIndex;
                    uint maxRows   = Math.Min((uint)bytesLeft / rowSize, rows);
                    if (maxRows == 0)
                    {
                        stream.Write(tempBuffer, 0, tempBufferIndex);
                        tempBufferIndex = 0;

                        bytesLeft = tempBuffer.Length;
                        maxRows   = Math.Min((uint)bytesLeft / rowSize, rows);
                    }
                    Debug.Assert(maxRows > 0);

                    for (uint endRowIndex = currentRowIndex + maxRows; currentRowIndex < endRowIndex; currentRowIndex++, tempBufferIndex += (int)rowSize)
                    {
                        tableWriter.WriteRow(currentRowIndex, columns, tempBuffer, tempBufferIndex);
                    }
                    rows -= maxRows;
                }
            }
            if (tempBufferIndex > 0)
            {
                stream.Write(tempBuffer, 0, tempBufferIndex);
            }
            if (tablesPos + totalSize != stream.Position)
            {
                throw new InvalidOperationException();
            }
        }