Example #1
0
 /// <summary>
 /// After the global header (see <see cref="ReadGlobalHeader"/> comes  list of custom debug info record.
 /// Each record begins with a standard header.
 /// </summary>
 public static void ReadRecordHeader(byte[] bytes, ref int offset, out byte version, out CustomDebugInfoKind kind, out int size)
 {
     version = bytes[offset + 0];
     kind = (CustomDebugInfoKind)bytes[offset + 1];
     size = BitConverter.ToInt32(bytes, offset + 4); //note: two bytes of padding after kind
     offset += CdiRecordHeaderSize;
 }
        /// <summary>
        /// After the global header (see <see cref="ReadGlobalHeader"/> comes list of custom debug info record.
        /// Each record begins with a standard header.
        /// </summary>
        private static void ReadRecordHeader(byte[] bytes, ref int offset, out byte version, out CustomDebugInfoKind kind, out int size, out int alignmentSize)
        {
            version = bytes[offset + 0];
            kind = (CustomDebugInfoKind)bytes[offset + 1];
            alignmentSize = bytes[offset + 3];

            // two bytes of padding after kind
            size = BitConverter.ToInt32(bytes, offset + 4);

            offset += CDI.CdiRecordHeaderSize;
        }
        /// <exception cref="InvalidOperationException"></exception>
        public static ImmutableArray<byte> TryGetCustomDebugInfoRecord(byte[] customDebugInfo, CustomDebugInfoKind recordKind)
        {
            foreach (var record in GetCustomDebugInfoRecords(customDebugInfo))
            {
                if (record.Kind == recordKind)
                {
                    return record.Data;
                }
            }

            return default(ImmutableArray<byte>);
        }
Example #4
0
 public CustomDebugInfoRecord(CustomDebugInfoKind kind, byte version, ImmutableArray <byte> data)
 {
     this.Kind    = kind;
     this.Version = version;
     this.Data    = data;
 }
Example #5
0
        /// <exception cref="InvalidOperationException"></exception>
        public static ImmutableArray <byte> TryGetCustomDebugInfoRecord(byte[] customDebugInfo, CustomDebugInfoKind recordKind)
        {
            foreach (var record in GetCustomDebugInfoRecords(customDebugInfo))
            {
                if (record.Kind == recordKind)
                {
                    return(record.Data);
                }
            }

            return(default(ImmutableArray <byte>));
        }
Example #6
0
        /// <summary>
        /// After the global header (see <see cref="ReadGlobalHeader"/> comes list of custom debug info record.
        /// Each record begins with a standard header.
        /// </summary>
        private static void ReadRecordHeader(byte[] bytes, ref int offset, out byte version, out CustomDebugInfoKind kind, out int size, out int alignmentSize)
        {
            version       = bytes[offset + 0];
            kind          = (CustomDebugInfoKind)bytes[offset + 1];
            alignmentSize = bytes[offset + 3];

            // two bytes of padding after kind
            size = BitConverter.ToInt32(bytes, offset + 4);

            offset += CDI.CdiRecordHeaderSize;
        }
 public CustomDebugInfoRecord(CustomDebugInfoKind kind, byte version, ImmutableArray<byte> data)
 {
     this.Kind = kind;
     this.Version = version;
     this.Data = data;
 }
Example #8
0
        /// <summary>
        /// Contains a name string.
        /// TODO: comment when the structure is understood.
        /// </summary>
        /// <remarks>
        /// Appears when are iterator methods.
        /// </remarks>
        private void WriteForwardIteratorCustomDebugInfo(byte version, CustomDebugInfoKind kind, int size, byte[] bytes, ref int offset)
        {
            Debug.Assert(kind == CustomDebugInfoKind.ForwardIterator);

            writer.WriteStartElement("forwardIterator");

            WriteCustomDebugInfoRecordHeaderAttributes(version, kind, size);

            string name;
            CDI.ReadForwardIteratorRecord(bytes, ref offset, size, out name);

            writer.WriteAttributeString("name", name);

            writer.WriteEndElement(); //forwardIterator
        }
Example #9
0
        /// <summary>
        /// Contains a list of buckets, each of which contains a number of flags, a slot ID, and a name.
        /// TODO: comment when the structure is understood.
        /// </summary>
        /// <remarks>
        /// Appears when there are dynamic locals.
        /// </remarks>
        private void WriteDynamicLocalsCustomDebugInfo(byte version, CustomDebugInfoKind kind, int size, byte[] bytes, ref int offset)
        {
            Debug.Assert(kind == CustomDebugInfoKind.DynamicLocals);

            writer.WriteStartElement("dynamicLocals");

            WriteCustomDebugInfoRecordHeaderAttributes(version, kind, size);

            ImmutableArray<DynamicLocalBucket> buckets;
            CDI.ReadDynamicLocalsRecord(bytes, ref offset, size, out buckets);

            writer.WriteAttributeString("bucketCount", buckets.Length.ToString());

            foreach (DynamicLocalBucket bucket in buckets)
            {
                ulong flags = bucket.Flags;
                int flagCount = bucket.FlagCount;

                PooledStringBuilder pooled = PooledStringBuilder.GetInstance();
                StringBuilder flagsBuilder = pooled.Builder;
                for (int f = 0; f < flagCount; f++)
                {
                    flagsBuilder.Append((flags >> f) & 1UL);
                }

                writer.WriteStartElement("bucket");
                writer.WriteAttributeString("flagCount", flagCount.ToString());
                writer.WriteAttributeString("flags", pooled.ToStringAndFree());
                writer.WriteAttributeString("slotId", bucket.SlotId.ToString());
                writer.WriteAttributeString("localName", bucket.Name);
                writer.WriteEndElement(); //bucket
            }

            writer.WriteEndElement(); //dynamicLocals
        }
Example #10
0
        /// <summary>
        /// This indicates that further information can be obtained by looking at the custom debug
        /// info of another method (specified by token).
        /// </summary>
        /// <remarks>
        /// Appears when there are extern aliases and edit-and-continue is disabled.
        /// Emitting tokens makes tests more fragile.
        /// </remarks>
        private void WriteForwardToModuleCustomDebugInfo(byte version, CustomDebugInfoKind kind, int size, byte[] bytes, ref int offset)
        {
            Debug.Assert(kind == CustomDebugInfoKind.ForwardToModuleInfo);

            writer.WriteStartElement("forwardToModule");

            WriteCustomDebugInfoRecordHeaderAttributes(version, kind, size);

            int token;
            CDI.ReadForwardRecord(bytes, ref offset, size, out token);
            WriteMethodAttributes(token, isReference: true);

            writer.WriteEndElement(); //forwardToModule
        }
Example #11
0
        /// <summary>
        /// Appears when iterator locals have to lifted into fields.  Contains a list of buckets with
        /// start and end offsets (presumably, into IL).
        /// TODO: comment when the structure is understood.
        /// </summary>
        /// <remarks>
        /// Appears when there are locals in iterator methods.
        /// </remarks>
        private void WriteIteratorLocalsCustomDebugInfo(byte version, CustomDebugInfoKind kind, int size, byte[] bytes, ref int offset)
        {
            Debug.Assert(kind == CustomDebugInfoKind.IteratorLocals);

            writer.WriteStartElement("iteratorLocals");

            WriteCustomDebugInfoRecordHeaderAttributes(version, kind, size);

            ImmutableArray<IteratorLocalBucket> buckets;
            CDI.ReadIteratorLocalsRecord(bytes, ref offset, size, out buckets);

            writer.WriteAttributeString("bucketCount", buckets.Length.ToString());

            foreach (IteratorLocalBucket bucket in buckets)
            {
                writer.WriteStartElement("bucket");
                writer.WriteAttributeString("startOffset", AsILOffset(bucket.StartOffset));
                writer.WriteAttributeString("endOffset", AsILOffset(bucket.EndOffset));
                writer.WriteEndElement(); //bucket
            }

            writer.WriteEndElement(); //iteratorLocals
        }
Example #12
0
        /// <summary>
        /// For each namespace declaration enclosing a method (innermost-to-outermost), there is a count
        /// of the number of imports in that declaration.
        /// </summary>
        /// <remarks>
        /// There's always at least one entry (for the global namespace).
        /// </remarks>
        private void WriteUsingCustomDebugInfo(byte version, CustomDebugInfoKind kind, int size, byte[] bytes, ref int offset)
        {
            Debug.Assert(kind == CustomDebugInfoKind.UsingInfo);

            writer.WriteStartElement("using");

            WriteCustomDebugInfoRecordHeaderAttributes(version, kind, size);

            ImmutableArray<short> counts;
            CDI.ReadUsingRecord(bytes, ref offset, size, out counts);

            writer.WriteAttributeString("namespaceCount", counts.Length.ToString());

            foreach (short importCount in counts)
            {
                writer.WriteStartElement("namespace");
                writer.WriteAttributeString("usingCount", importCount.ToString());
                writer.WriteEndElement(); //namespace
            }

            writer.WriteEndElement(); //using
        }
Example #13
0
        /// <summary>
        /// If the custom debug info is in a format that we don't understand, then we will
        /// just print a standard record header followed by the rest of the record as a
        /// single hex string.
        /// </summary>
        private void WriteUnknownCustomDebugInfo(byte version, CustomDebugInfoKind kind, int size, byte[] bytes, ref int offset)
        {
            writer.WriteStartElement("unknown");

            WriteCustomDebugInfoRecordHeaderAttributes(version, kind, size);

            ImmutableArray<byte> body;
            CDI.ReadUnknownRecord(bytes, ref offset, size, out body);

            PooledStringBuilder pooled = PooledStringBuilder.GetInstance();
            StringBuilder builder = pooled.Builder;
            foreach (byte b in body)
            {
                builder.AppendFormat("{0:X2}", b);
            }
            writer.WriteAttributeString("payload", pooled.ToStringAndFree());

            writer.WriteEndElement(); //unknown
        }
Example #14
0
 /// <summary>
 /// Write version, kind, and size attributes.
 /// </summary>
 private void WriteCustomDebugInfoRecordHeaderAttributes(byte version, CustomDebugInfoKind kind, int size)
 {
     writer.WriteAttributeString("version", version.ToString());
     writer.WriteAttributeString("kind", kind.ToString());
     writer.WriteAttributeString("size", size.ToString());
 }
 /// <summary>
 /// After the global header (see <see cref="ReadGlobalHeader"/> comes  list of custom debug info record.
 /// Each record begins with a standard header.
 /// </summary>
 public static void ReadRecordHeader(byte[] bytes, ref int offset, out byte version, out CustomDebugInfoKind kind, out int size)
 {
     version = bytes[offset + 0];
     kind    = (CustomDebugInfoKind)bytes[offset + 1];
     size    = BitConverter.ToInt32(bytes, offset + 4); //note: two bytes of padding after kind
     offset += CdiRecordHeaderSize;
 }
Example #16
0
        private static PooledBlobBuilder SerializeRecord(
            CustomDebugInfoKind kind,
            EditAndContinueMethodDebugInformation debugInfo,
            Action<EditAndContinueMethodDebugInformation, BlobBuilder> recordSerializer)
        {
            var cmw = PooledBlobBuilder.GetInstance();
            cmw.WriteByte(CustomDebugInfoConstants.Version);
            cmw.WriteByte((byte)kind);
            cmw.WriteByte(0);

            // alignment size and length (will be patched)
            var alignmentSizeAndLengthWriter = new BlobWriter(cmw.ReserveBytes(sizeof(byte) + sizeof(uint)));

            recordSerializer(debugInfo, cmw);

            int length = cmw.Count;
            int alignedLength = 4 * ((length + 3) / 4);
            byte alignmentSize = (byte)(alignedLength - length);
            cmw.WriteBytes(0, alignmentSize);

            // fill in alignment size and length:
            alignmentSizeAndLengthWriter.WriteByte(alignmentSize);
            alignmentSizeAndLengthWriter.WriteUInt32((uint)alignedLength);

            return cmw;
        }