Beispiel #1
0
        private void WriteDirectory(Directory directory, BlobBuilder writer, uint offset, uint level, uint sizeOfDirectoryTree, int virtualAddressBase, BlobBuilder dataWriter)
        {
            writer.WriteUInt32(0); // Characteristics
            writer.WriteUInt32(0); // Timestamp
            writer.WriteUInt32(0); // Version
            writer.WriteUInt16(directory.NumberOfNamedEntries);
            writer.WriteUInt16(directory.NumberOfIdEntries);
            uint n = (uint)directory.Entries.Count;
            uint k = offset + 16 + n * 8;
            for (int i = 0; i < n; i++)
            {
                int id;
                string name;
                uint nameOffset = (uint)dataWriter.Position + sizeOfDirectoryTree;
                uint directoryOffset = k;
                Directory subDir = directory.Entries[i] as Directory;
                if (subDir != null)
                {
                    id = subDir.ID;
                    name = subDir.Name;
                    if (level == 0)
                    {
                        k += SizeOfDirectory(subDir);
                    }
                    else
                    {
                        k += 16 + 8 * (uint)subDir.Entries.Count;
                    }
                }
                else
                {
                    //EDMAURER write out an IMAGE_RESOURCE_DATA_ENTRY followed
                    //immediately by the data that it refers to. This results
                    //in a layout different than that produced by pulling the resources
                    //from an OBJ. In that case all of the data bits of a resource are
                    //contiguous in .rsrc$02. After processing these will end up at
                    //the end of .rsrc following all of the directory
                    //info and IMAGE_RESOURCE_DATA_ENTRYs
                    IWin32Resource r = (IWin32Resource)directory.Entries[i];
                    id = level == 0 ? r.TypeId : level == 1 ? r.Id : (int)r.LanguageId;
                    name = level == 0 ? r.TypeName : level == 1 ? r.Name : null;
                    dataWriter.WriteUInt32((uint)(virtualAddressBase + sizeOfDirectoryTree + 16 + dataWriter.Position));
                    byte[] data = new List<byte>(r.Data).ToArray();
                    dataWriter.WriteUInt32((uint)data.Length);
                    dataWriter.WriteUInt32(r.CodePage);
                    dataWriter.WriteUInt32(0);
                    dataWriter.WriteBytes(data);
                    while ((dataWriter.Count % 4) != 0)
                    {
                        dataWriter.WriteByte(0);
                    }
                }

                if (id >= 0)
                {
                    writer.WriteInt32(id);
                }
                else
                {
                    if (name == null)
                    {
                        name = string.Empty;
                    }

                    writer.WriteUInt32(nameOffset | 0x80000000);
                    dataWriter.WriteUInt16((ushort)name.Length);
                    dataWriter.WriteUTF16(name);
                }

                if (subDir != null)
                {
                    writer.WriteUInt32(directoryOffset | 0x80000000);
                }
                else
                {
                    writer.WriteUInt32(nameOffset);
                }
            }

            k = offset + 16 + n * 8;
            for (int i = 0; i < n; i++)
            {
                Directory subDir = directory.Entries[i] as Directory;
                if (subDir != null)
                {
                    this.WriteDirectory(subDir, writer, k, level + 1, sizeOfDirectoryTree, virtualAddressBase, dataWriter);
                    if (level == 0)
                    {
                        k += SizeOfDirectory(subDir);
                    }
                    else
                    {
                        k += 16 + 8 * (uint)subDir.Entries.Count;
                    }
                }
            }
        }
Beispiel #2
0
        public unsafe void Write_Errors()
        {
            var builder = new BlobBuilder(16);
            Assert.Throws<ArgumentNullException>(() => builder.WriteUTF16((char[])null));
            Assert.Throws<ArgumentNullException>(() => builder.WriteUTF16((string)null));
            Assert.Throws<ArgumentNullException>(() => builder.WriteUTF8(null, allowUnpairedSurrogates: true));
            Assert.Throws<ArgumentNullException>(() => builder.WriteUTF8(null, allowUnpairedSurrogates: true));
            Assert.Throws<ArgumentNullException>(() => builder.TryWriteBytes((Stream)null, 0));
            Assert.Throws<ArgumentNullException>(() => builder.WriteBytes(null));
            Assert.Throws<ArgumentNullException>(() => builder.WriteBytes(null, 0, 0));
            Assert.Throws<ArgumentNullException>(() => builder.WriteBytes((byte*)null, 0));
            Assert.Throws<ArgumentNullException>(() => builder.WriteBytes(default(ImmutableArray<byte>)));
            Assert.Throws<ArgumentNullException>(() => builder.WriteBytes(default(ImmutableArray<byte>), 0, 0));

            var bw = default(BlobWriter);
            Assert.Throws<ArgumentNullException>(() => builder.WriteContentTo(ref bw));
            Assert.Throws<ArgumentNullException>(() => builder.WriteContentTo((Stream)null));
            Assert.Throws<ArgumentNullException>(() => builder.WriteContentTo((BlobBuilder)null));

            Assert.Throws<ArgumentOutOfRangeException>(() => builder.TryWriteBytes(new MemoryStream(), -1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(0, -1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(new byte[] { }, 1, 0));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(new byte[] { }, 0, 1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(new byte[] { }, 0, -1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(ImmutableArray<byte>.Empty, 1, 0));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(ImmutableArray<byte>.Empty, 0, 1));
            Assert.Throws<ArgumentOutOfRangeException>(() => builder.WriteBytes(ImmutableArray<byte>.Empty, 1, -1));
        }
Beispiel #3
0
        public void WriteUTF16()
        {
            var writer = new BlobBuilder(4);

            writer.WriteUTF16("");
            writer.WriteUTF16("a");
            writer.WriteUTF16("");
            writer.WriteUTF16(new char[0]);

            writer.WriteUTF16(new char[] { '\ud800' });           // hi surrogate
            writer.WriteUTF16("\udc00");                          // lo surrogate
            writer.WriteUTF16("\ud800\udc00");                    // pair
            writer.WriteUTF16(new char[] { '\udc00', '\ud800' }); // lo + hi
            writer.WriteUTF16("\u1234");

            AssertEx.Equal(new byte[]
            {
                0x61, 0x00,
                0x00, 0xD8,
                0x00, 0xDC,
                0x00, 0xD8, 0x00, 0xDC,
                0x00, 0xDC, 0x00, 0xD8,
                0x34, 0x12
            }, writer.ToArray());
        }
Beispiel #4
0
        public void Link()
        {
            var builder1 = new BlobBuilder(16);
            builder1.WriteByte(1);

            var builder2 = new BlobBuilder(16);
            builder2.WriteByte(2);

            var builder3 = new BlobBuilder(16);
            builder3.WriteByte(3);

            var builder4 = new BlobBuilder(16);
            builder4.WriteByte(4);

            var builder5 = new BlobBuilder(16);
            builder5.WriteByte(5);

            builder2.LinkPrefix(builder1);
            AssertEx.Equal(new byte[] { 1, 2 }, builder2.ToArray());
            Assert.Throws<InvalidOperationException>(() => builder1.ToArray());
            Assert.Throws<InvalidOperationException>(() => builder2.LinkPrefix(builder1));
            Assert.Throws<InvalidOperationException>(() => builder1.WriteByte(0xff));
            Assert.Throws<InvalidOperationException>(() => builder1.WriteBytes(1, 10));
            Assert.Throws<InvalidOperationException>(() => builder1.WriteBytes(new byte[] { 1 }));
            Assert.Throws<InvalidOperationException>(() => builder1.ReserveBytes(1));
            Assert.Throws<InvalidOperationException>(() => builder1.GetBlobs());
            Assert.Throws<InvalidOperationException>(() => builder1.ContentEquals(builder1));
            Assert.Throws<InvalidOperationException>(() => builder1.WriteUTF16("str"));
            Assert.Throws<InvalidOperationException>(() => builder1.WriteUTF8("str", allowUnpairedSurrogates: false));

            builder2.LinkSuffix(builder3);
            AssertEx.Equal(new byte[] { 1, 2, 3 }, builder2.ToArray());
            Assert.Throws<InvalidOperationException>(() => builder3.LinkPrefix(builder5));

            builder2.LinkPrefix(builder4);
            AssertEx.Equal(new byte[] { 4, 1, 2, 3 }, builder2.ToArray());
            Assert.Throws<InvalidOperationException>(() => builder4.LinkPrefix(builder5));

            builder2.LinkSuffix(builder5);
            AssertEx.Equal(new byte[] { 4, 1, 2, 3, 5 }, builder2.ToArray());
        }
        private BlobHandle SerializeLocalConstantSignature(ILocalDefinition localConstant)
        {
            var builder = new BlobBuilder();

            // TODO: BlobEncoder.LocalConstantSignature

            // CustomMod*
            var encoder = new CustomModifiersEncoder(builder);

            SerializeCustomModifiers(encoder, localConstant.CustomModifiers);

            var type     = localConstant.Type;
            var typeCode = type.TypeCode;

            object value = localConstant.CompileTimeValue.Value;

            // PrimitiveConstant or EnumConstant
            if (value is decimal)
            {
                builder.WriteByte((byte)SignatureTypeKind.ValueType);
                builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type)));

                builder.WriteDecimal((decimal)value);
            }
            else if (value is DateTime)
            {
                builder.WriteByte((byte)SignatureTypeKind.ValueType);
                builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type)));

                builder.WriteDateTime((DateTime)value);
            }
            else if (typeCode == PrimitiveTypeCode.String)
            {
                builder.WriteByte((byte)ConstantTypeCode.String);
                if (value == null)
                {
                    builder.WriteByte(0xff);
                }
                else
                {
                    builder.WriteUTF16((string)value);
                }
            }
            else if (value != null)
            {
                // TypeCode
                builder.WriteByte((byte)GetConstantTypeCode(value));

                // Value
                builder.WriteConstant(value);

                // EnumType
                if (type.IsEnum)
                {
                    builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type)));
                }
            }
            else if (this.module.IsPlatformType(type, PlatformType.SystemObject))
            {
                builder.WriteByte((byte)SignatureTypeCode.Object);
            }
            else
            {
                builder.WriteByte((byte)(type.IsValueType ? SignatureTypeKind.ValueType : SignatureTypeKind.Class));
                builder.WriteCompressedInteger(CodedIndex.TypeDefOrRefOrSpec(GetTypeHandle(type)));
            }

            return(_debugMetadataOpt.GetOrAddBlob(builder));
        }
Beispiel #6
0
        internal static void WriteConstant(BlobBuilder writer, object value)
        {
            if (value == null)
            {
                // The encoding of Type for the nullref value for FieldInit is ELEMENT_TYPE_CLASS with a Value of a 32-bit.
                writer.WriteUInt32(0);
                return;
            }

            var type = value.GetType();
            if (type.GetTypeInfo().IsEnum)
            {
                type = Enum.GetUnderlyingType(type);
            }

            if (type == typeof(bool))
            {
                writer.WriteBoolean((bool)value);
            }
            else if (type == typeof(int))
            {
                writer.WriteInt32((int)value);
            }
            else if (type == typeof(string))
            {
                writer.WriteUTF16((string)value);
            }
            else if (type == typeof(byte))
            {
                writer.WriteByte((byte)value);
            }
            else if (type == typeof(char))
            {
                writer.WriteUInt16((char)value);
            }
            else if (type == typeof(double))
            {
                writer.WriteDouble((double)value);
            }
            else if (type == typeof(short))
            {
                writer.WriteInt16((short)value);
            }
            else if (type == typeof(long))
            {
                writer.WriteInt64((long)value);
            }
            else if (type == typeof(sbyte))
            {
                writer.WriteSByte((sbyte)value);
            }
            else if (type == typeof(float))
            {
                writer.WriteSingle((float)value);
            }
            else if (type == typeof(ushort))
            {
                writer.WriteUInt16((ushort)value);
            }
            else if (type == typeof(uint))
            {
                writer.WriteUInt32((uint)value);
            }
            else if (type == typeof(ulong))
            {
                writer.WriteUInt64((ulong)value);
            }
            else
            {
                // TODO: message
                throw new ArgumentException();
            }
        }
Beispiel #7
0
        /// <exception cref="ImageFormatLimitationException">The remaining space on the heap is too small to fit the string.</exception>
        public UserStringHandle GetOrAddUserString(string str)
        {
            int index;

            if (!_userStrings.TryGetValue(str, out index))
            {
                Debug.Assert(!_streamsAreComplete);

                int startPosition = _userStringWriter.Position;
                int encodedLength = str.Length * 2 + 1;
                index = startPosition + _userStringHeapStartOffset;

                // Native metadata emitter allows strings to exceed the heap size limit as long
                // as the index is within the limits (see https://github.com/dotnet/roslyn/issues/9852)
                if (index > UserStringHeapSizeLimit)
                {
                    ImageFormatLimitationException.ThrowHeapSizeLimitExceeded(HeapIndex.UserString);
                }

                _userStrings.Add(str, index);
                _userStringWriter.WriteCompressedInteger(encodedLength);
                _userStringWriter.WriteUTF16(str);

                // Write out a trailing byte indicating if the string is really quite simple
                byte stringKind = 0;
                foreach (char ch in str)
                {
                    if (ch >= 0x7F)
                    {
                        stringKind = 1;
                    }
                    else
                    {
                        switch ((int)ch)
                        {
                        case 0x1:
                        case 0x2:
                        case 0x3:
                        case 0x4:
                        case 0x5:
                        case 0x6:
                        case 0x7:
                        case 0x8:
                        case 0xE:
                        case 0xF:
                        case 0x10:
                        case 0x11:
                        case 0x12:
                        case 0x13:
                        case 0x14:
                        case 0x15:
                        case 0x16:
                        case 0x17:
                        case 0x18:
                        case 0x19:
                        case 0x1A:
                        case 0x1B:
                        case 0x1C:
                        case 0x1D:
                        case 0x1E:
                        case 0x1F:
                        case 0x27:
                        case 0x2D:
                            stringKind = 1;
                            break;

                        default:
                            continue;
                        }
                    }

                    break;
                }

                _userStringWriter.WriteByte(stringKind);
            }

            return(MetadataTokens.UserStringHandle(index));
        }
Beispiel #8
0
        public int GetUserStringToken(string str)
        {
            int index;

            if (!_userStrings.TryGetValue(str, out index))
            {
                Debug.Assert(!_streamsAreComplete);

                index = _userStringWriter.Position + _userStringHeapStartOffset;
                _userStrings.Add(str, index);
                _userStringWriter.WriteCompressedInteger((uint)str.Length * 2 + 1);

                _userStringWriter.WriteUTF16(str);

                // Write out a trailing byte indicating if the string is really quite simple
                byte stringKind = 0;
                foreach (char ch in str)
                {
                    if (ch >= 0x7F)
                    {
                        stringKind = 1;
                    }
                    else
                    {
                        switch ((int)ch)
                        {
                        case 0x1:
                        case 0x2:
                        case 0x3:
                        case 0x4:
                        case 0x5:
                        case 0x6:
                        case 0x7:
                        case 0x8:
                        case 0xE:
                        case 0xF:
                        case 0x10:
                        case 0x11:
                        case 0x12:
                        case 0x13:
                        case 0x14:
                        case 0x15:
                        case 0x16:
                        case 0x17:
                        case 0x18:
                        case 0x19:
                        case 0x1A:
                        case 0x1B:
                        case 0x1C:
                        case 0x1D:
                        case 0x1E:
                        case 0x1F:
                        case 0x27:
                        case 0x2D:
                            stringKind = 1;
                            break;

                        default:
                            continue;
                        }
                    }

                    break;
                }

                _userStringWriter.WriteByte(stringKind);
            }

            return(0x70000000 | index);
        }