示例#1
0
 private int ComputeSizeOfDebugDirectoryData()
 {
     // The debug directory data is only needed if this.EmitPdb.
     return((!EmitPdb) ? 0 :
            4 +            // 4B signature "RSDS"
            16 +           // GUID
            sizeof(uint) + // Age
            Math.Max(BlobUtilities.GetUTF8ByteCount(PdbPathOpt) + 1, MinPdbPath));
 }
示例#2
0
        /// <summary>
        /// Writes string in User String (#US) heap format (see ECMA-335-II 24.2.4 #US and #Blob heaps):
        /// </summary>
        /// <remarks>
        /// The string is UTF16 encoded and prefixed by the its size in bytes.
        ///
        /// This final byte holds the value 1 if and only if any UTF16 character within the string has any bit set in its top byte,
        /// or its low byte is any of the following: 0x01–0x08, 0x0E–0x1F, 0x27, 0x2D, 0x7F. Otherwise, it holds 0.
        /// The 1 signifies Unicode characters that require handling beyond that normally provided for 8-bit encoding sets.
        /// </remarks>
        /// <exception cref="InvalidOperationException">Builder is not writable, it has been linked with another one.</exception>
        public void WriteUserString(string value)
        {
            if (value == null)
            {
                throw new ArgumentNullException(nameof(value));
            }

            WriteCompressedInteger(BlobUtilities.GetUserStringByteLength(BlobUtilities.GetUTF8ByteCount(value)));
            WriteUTF8(value, false);
            WriteByte(BlobUtilities.GetUserStringTrailingByte(value));
        }
示例#3
0
        private void TestGetUTF8ByteCount(int expectedCount, string expectedRemainder, string str, int charCount, int byteLimit)
        {
            fixed(char *ptr = str)
            {
                char *remainderPtr;

                Assert.Equal(expectedCount, BlobUtilities.GetUTF8ByteCount(ptr, charCount, byteLimit, out remainderPtr));

                string remainder = new string(remainderPtr);

                Assert.Equal(expectedRemainder, remainder);
            }
        }
示例#4
0
        private void WriteUTF8(string str, int start, int length, bool allowUnpairedSurrogates, bool prependSize)
        {
            fixed (char* strPtr = str)
            {
                char* charPtr = strPtr + start;
                int byteCount = BlobUtilities.GetUTF8ByteCount(charPtr, length);

                if (prependSize)
                {
                    WriteCompressedInteger(byteCount);
                }

                int startOffset = Advance(byteCount);
                _buffer.WriteUTF8(startOffset, charPtr, length, byteCount, allowUnpairedSurrogates);
            }
        }
示例#5
0
        /// <summary>
        /// Creates a builder of a metadata root.
        /// </summary>
        /// <param name="tablesAndHeaps">
        /// Builder populated with metadata entities stored in tables and values stored in heaps.
        /// The entities and values will be enumerated when serializing the metadata root.
        /// </param>
        /// <param name="metadataVersion">
        /// The version string written to the metadata header. The default value is "v4.0.30319".
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="tablesAndHeaps"/> is null.</exception>
        /// <exception cref="ArgumentException"><paramref name="metadataVersion"/> is too long (the number of bytes when UTF8-encoded must be less than 255).</exception>
        public MetadataRootBuilder(MetadataBuilder tablesAndHeaps, string metadataVersion = null)
        {
            if (tablesAndHeaps == null)
            {
                Throw.ArgumentNull(nameof(tablesAndHeaps));
            }

            Debug.Assert(BlobUtilities.GetUTF8ByteCount(DefaultMetadataVersionString) == DefaultMetadataVersionString.Length);
            int metadataVersionByteCount = metadataVersion != null?BlobUtilities.GetUTF8ByteCount(metadataVersion) : DefaultMetadataVersionString.Length;

            if (metadataVersionByteCount > MetadataSizes.MaxMetadataVersionByteCount)
            {
                Throw.InvalidArgument(SR.MetadataVersionTooLong, nameof(metadataVersion));
            }

            _tablesAndHeaps     = tablesAndHeaps;
            MetadataVersion     = metadataVersion ?? DefaultMetadataVersionString;
            _serializedMetadata = tablesAndHeaps.GetSerializedMetadata(EmptyRowCounts, metadataVersionByteCount, isStandaloneDebugMetadata: false);
        }
示例#6
0
        internal unsafe void WriteUTF8(string str, int start, int length, bool allowUnpairedSurrogates, bool prependSize)
        {
            Debug.Assert(start >= 0);
            Debug.Assert(length >= 0);
            Debug.Assert(start + length <= str.Length);

            if (!IsHead)
            {
                Throw.InvalidOperationBuilderAlreadyLinked();
            }

            fixed(char *strPtr = str)
            {
                char *currentPtr = strPtr + start;
                char *nextPtr;

                // the max size of compressed int is 4B:
                int byteLimit = FreeBytes - (prependSize ? sizeof(uint) : 0);

                int bytesToCurrent = BlobUtilities.GetUTF8ByteCount(currentPtr, length, byteLimit, out nextPtr);
                int charsToCurrent = (int)(nextPtr - currentPtr);
                int charsToNext    = length - charsToCurrent;
                int bytesToNext    = BlobUtilities.GetUTF8ByteCount(nextPtr, charsToNext);

                if (prependSize)
                {
                    WriteCompressedInteger(bytesToCurrent + bytesToNext);
                }

                _buffer.WriteUTF8(Length, currentPtr, charsToCurrent, bytesToCurrent, allowUnpairedSurrogates);
                AddLength(bytesToCurrent);

                if (bytesToNext > 0)
                {
                    Expand(bytesToNext);

                    _buffer.WriteUTF8(0, nextPtr, charsToNext, bytesToNext, allowUnpairedSurrogates);
                    AddLength(bytesToNext);
                }
            }
        }
示例#7
0
        /// <summary>
        /// Creates a builder of a Portable PDB image.
        /// </summary>
        /// <param name="tablesAndHeaps">
        /// Builder populated with debug metadata entities stored in tables and values stored in heaps.
        /// The entities and values will be enumerated when serializing the Portable PDB image.
        /// </param>
        /// <param name="typeSystemRowCounts">
        /// Row counts of all tables that the associated type-system metadata contain.
        /// Each slot in the array corresponds to a table (<see cref="TableIndex"/>).
        /// The length of the array must be equal to <see cref="MetadataTokens.TableCount"/>.
        /// </param>
        /// <param name="entryPoint">
        /// Entry point method definition handle.
        /// </param>
        /// <param name="idProvider">
        /// Function calculating id of content represented as a sequence of blobs.
        /// If not specified a default function that ignores the content and returns current time-based content id is used
        /// (<see cref="BlobContentId.GetTimeBasedProvider()"/>).
        /// You must specify a deterministic function to produce a deterministic Portable PDB image.
        /// </param>
        /// <exception cref="ArgumentNullException"><paramref name="tablesAndHeaps"/> or <paramref name="typeSystemRowCounts"/> is null.</exception>
        public PortablePdbBuilder(
            MetadataBuilder tablesAndHeaps,
            ImmutableArray <int> typeSystemRowCounts,
            MethodDefinitionHandle entryPoint,
            Func <IEnumerable <Blob>, BlobContentId>?idProvider = null)
        {
            if (tablesAndHeaps == null)
            {
                Throw.ArgumentNull(nameof(tablesAndHeaps));
            }

            ValidateTypeSystemRowCounts(typeSystemRowCounts);

            _builder    = tablesAndHeaps;
            _entryPoint = entryPoint;

            Debug.Assert(BlobUtilities.GetUTF8ByteCount(MetadataVersion) == MetadataVersion.Length);
            _serializedMetadata = tablesAndHeaps.GetSerializedMetadata(typeSystemRowCounts, MetadataVersion.Length, isStandaloneDebugMetadata: true);

            IdProvider = idProvider ?? BlobContentId.GetTimeBasedProvider();
        }
示例#8
0
        private void WriteUTF8(string str, int start, int length, bool allowUnpairedSurrogates, bool prependSize)
        {
            if (!IsHead)
            {
                ThrowHeadRequired();
            }

            fixed(char *strPtr = str)
            {
                char *currentPtr = strPtr + start;
                char *nextPtr;

                // the max size of compressed int is 4B:
                int byteLimit = FreeBytes - (prependSize ? sizeof(uint) : 0);

                int bytesToCurrent = BlobUtilities.GetUTF8ByteCount(currentPtr, length, byteLimit, out nextPtr);
                int charsToCurrent = (int)(nextPtr - currentPtr);
                int charsToNext    = str.Length - charsToCurrent;
                int bytesToNext    = BlobUtilities.GetUTF8ByteCount(nextPtr, charsToNext);

                if (prependSize)
                {
                    WriteCompressedInteger(bytesToCurrent + bytesToNext);
                }

                _buffer.WriteUTF8(Length, currentPtr, charsToCurrent, bytesToCurrent, allowUnpairedSurrogates);
                AddLength(bytesToCurrent);

                if (bytesToNext > 0)
                {
                    Expand(bytesToNext);

                    _buffer.WriteUTF8(0, nextPtr, charsToNext, bytesToNext, allowUnpairedSurrogates);
                    AddLength(bytesToNext);
                }
            }
        }
        /// <summary>
        /// Fills in stringIndexMap with data from stringIndex and write to stringWriter.
        /// Releases stringIndex as the stringTable is sealed after this point.
        /// </summary>
        private void SerializeStringHeap()
        {
            // Sort by suffix and remove stringIndex
            var sorted = new List <KeyValuePair <string, StringHandle> >(_strings);

            sorted.Sort(new SuffixSort());
            _strings = null;

            _stringWriter = new BlobBuilder(1024);

            // Create VirtIdx to Idx map and add entry for empty string
            _stringIndexToResolvedOffsetMap = new int[sorted.Count + 1];

            _stringIndexToResolvedOffsetMap[0] = 0;
            _stringWriter.WriteByte(0);

            // Find strings that can be folded
            string prev = string.Empty;

            foreach (KeyValuePair <string, StringHandle> entry in sorted)
            {
                int position = _stringHeapStartOffset + _stringWriter.Position;

                // It is important to use ordinal comparison otherwise we'll use the current culture!
                if (prev.EndsWith(entry.Key, StringComparison.Ordinal) && !BlobUtilities.IsLowSurrogateChar(entry.Key[0]))
                {
                    // Map over the tail of prev string. Watch for null-terminator of prev string.
                    _stringIndexToResolvedOffsetMap[MetadataTokens.GetHeapOffset(entry.Value)] = position - (BlobUtilities.GetUTF8ByteCount(entry.Key) + 1);
                }
                else
                {
                    _stringIndexToResolvedOffsetMap[MetadataTokens.GetHeapOffset(entry.Value)] = position;
                    _stringWriter.WriteUTF8(entry.Key, allowUnpairedSurrogates: false);
                    _stringWriter.WriteByte(0);
                }

                prev = entry.Key;
            }
        }
示例#10
0
        /// <summary>
        /// Fills in stringIndexMap with data from stringIndex and write to stringWriter.
        /// Releases stringIndex as the stringTable is sealed after this point.
        /// </summary>
        private static ImmutableArray <int> SerializeStringHeap(
            BlobBuilder heapBuilder,
            Dictionary <string, StringHandle> strings,
            int stringHeapStartOffset)
        {
            // Sort by suffix and remove stringIndex
            var sorted = new List <KeyValuePair <string, StringHandle> >(strings);

            sorted.Sort(SuffixSort.Instance);

            // Create VirtIdx to Idx map and add entry for empty string
            int totalCount = sorted.Count + 1;
            var stringVirtualIndexToHeapOffsetMap = ImmutableArray.CreateBuilder <int>(totalCount);

            stringVirtualIndexToHeapOffsetMap.Count = totalCount;

            stringVirtualIndexToHeapOffsetMap[0] = 0;
            heapBuilder.WriteByte(0);

            // Find strings that can be folded
            string prev = string.Empty;

            foreach (KeyValuePair <string, StringHandle> entry in sorted)
            {
                int position = stringHeapStartOffset + heapBuilder.Count;

                // It is important to use ordinal comparison otherwise we'll use the current culture!
                if (prev.EndsWith(entry.Key, StringComparison.Ordinal) && !BlobUtilities.IsLowSurrogateChar(entry.Key[0]))
                {
                    // Map over the tail of prev string. Watch for null-terminator of prev string.
                    stringVirtualIndexToHeapOffsetMap[entry.Value.GetWriterVirtualIndex()] = position - (BlobUtilities.GetUTF8ByteCount(entry.Key) + 1);
                }
                else
                {
                    stringVirtualIndexToHeapOffsetMap[entry.Value.GetWriterVirtualIndex()] = position;
                    heapBuilder.WriteUTF8(entry.Key, allowUnpairedSurrogates: false);
                    heapBuilder.WriteByte(0);
                }

                prev = entry.Key;
            }

            return(stringVirtualIndexToHeapOffsetMap.MoveToImmutable());
        }