Example #1
0
        protected void WriteData(MDWriterStream stream, List <byte[]> newData, byte[] tempBuffer)
        {
            if (newData.Count == 0)
            {
                return;
            }
            int tempBufferIndex = 0;

            foreach (var data in newData)
            {
                int bytesLeft = tempBuffer.Length - tempBufferIndex;
                if (data.Length > bytesLeft)
                {
                    stream.Write(tempBuffer, 0, tempBufferIndex);
                    tempBufferIndex = 0;
                }
                if (data.Length > tempBuffer.Length)
                {
                    Debug.Assert(tempBufferIndex == 0);
                    stream.Write(data);
                }
                else
                {
                    Array.Copy(data, 0, tempBuffer, tempBufferIndex, data.Length);
                    tempBufferIndex += data.Length;
                }
            }
            if (tempBufferIndex > 0)
            {
                stream.Write(tempBuffer, 0, tempBufferIndex);
            }
        }
Example #2
0
 public MDWriter(RawModuleBytes moduleData, MetadataEditor mdEditor, MDWriterStream stream)
 {
     this.moduleData = moduleData;
     this.mdEditor   = mdEditor;
     this.stream     = stream;
     sections        = new List <PESection>();
 }
Example #3
0
        public override void Finish(MDWriter mdWriter, MDWriterStream stream)
        {
            stream.Position = cor20HeaderMetadataDataDirPosition;
            Debug.Assert(mdData.RVA != 0);
            Debug.Assert(mdData.Size != 0);
            stream.Write(mdData.RVA);
            stream.Write(mdData.Size);

            if (!(snData is null))
            {
                stream.Position = cor20HeaderStrongnameDataDirPosition;
                Debug.Assert(snData.RVA != 0);
                Debug.Assert(snData.Size != 0);
                stream.Write(snData.RVA);
                stream.Write(snData.Size);
            }
        }
Example #4
0
        public override void Write(MDWriter mdWriter, uint rva, MDWriterStream stream)
        {
            mdWriter.WriteDataDirectory(14, rva, headerSize);
            stream.Write(headerSize);
            var cor20 = mdWriter.MetadataEditor.RealMetadata.ImageCor20Header;

            stream.Write(cor20.MajorRuntimeVersion);
            stream.Write(cor20.MinorRuntimeVersion);
            cor20HeaderMetadataDataDirPosition = stream.Position;
            stream.Position += 8;            // Metadata data directory, updated later
            var flags = cor20.Flags;

            flags &= ~ComImageFlags.NativeEntryPoint;
            if (snData is null)
            {
                flags &= ~ComImageFlags.StrongNameSigned;
            }
            else
            {
                flags |= ComImageFlags.StrongNameSigned;
            }
            stream.Write((uint)flags);
            if ((cor20.Flags & ComImageFlags.NativeEntryPoint) == 0)
            {
                stream.Write(cor20.EntryPointToken_or_RVA);
            }
            else
            {
                stream.Position += 4;
            }
            stream.Position += 8;            // .NET resources
            cor20HeaderStrongnameDataDirPosition = stream.Position;
            stream.Position += 8;            // Strong name signature
            stream.Position += 8;            // Code manager table
            stream.Position += 8;            // Vtable fixups
            stream.Position += 8;            // Export address table jumps
            stream.Position += 8;            // Managed native header
        }
        public override void Write(MDWriter mdWriter, uint rva, MDWriterStream stream)
        {
            RVA = rva;
            var startPos = stream.Position;

            // PERF: We only write the known needed heaps. The #US heap isn't written since
            // it's only used by method bodies and we don't write method bodies.
            var heapWriters = new List <MDHeapWriter>(4);

            heapWriters.Add(new TablesHeapWriter(mdEditor.TablesHeap, mdEditor.StringsHeap, mdEditor.GuidHeap, mdEditor.BlobHeap));
            if (mdEditor.StringsHeap.ExistsInMetadata || mdEditor.StringsHeap.MustRewriteHeap())
            {
                heapWriters.Add(new StringsHeapWriter(mdEditor.StringsHeap));
            }
            if (mdEditor.GuidHeap.ExistsInMetadata || mdEditor.GuidHeap.MustRewriteHeap())
            {
                heapWriters.Add(new GuidHeapWriter(mdEditor.GuidHeap));
            }
            if (mdEditor.BlobHeap.ExistsInMetadata || mdEditor.BlobHeap.MustRewriteHeap())
            {
                heapWriters.Add(new BlobHeapWriter(mdEditor.BlobHeap));
            }

            var heapInfos = new(long offsetAndSizePosition, long dataPosition, long dataEndPosition)[heapWriters.Count];
Example #6
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();
            }
        }
Example #7
0
 public abstract void Write(MDWriter mdWriter, MDWriterStream stream, byte[] tempBuffer);