Beispiel #1
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(CustomDebugInfoRecord record)
        {
            Debug.Assert(record.Kind == CustomDebugInfoKind.DynamicLocals);

            writer.WriteStartElement("dynamicLocals");

            var buckets = CDI.DecodeDynamicLocalsRecord(record.Data);

            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
        }
Beispiel #2
0
        /// <summary>
        /// Contains a name string.
        /// TODO: comment when the structure is understood.
        /// </summary>
        /// <remarks>
        /// Appears when are iterator methods.
        /// </remarks>
        private void WriteForwardIteratorCustomDebugInfo(CustomDebugInfoRecord record)
        {
            Debug.Assert(record.Kind == CustomDebugInfoKind.ForwardIterator);

            writer.WriteStartElement("forwardIterator");

            string name = CDI.DecodeForwardIteratorRecord(record.Data);

            writer.WriteAttributeString("name", name);

            writer.WriteEndElement(); //forwardIterator
        }
Beispiel #3
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(CustomDebugInfoRecord record)
        {
            Debug.Assert(record.Kind == CustomDebugInfoKind.ForwardToModuleInfo);

            writer.WriteStartElement("forwardToModule");

            int token = CDI.DecodeForwardRecord(record.Data);

            WriteMethodAttributes(token, isReference: true);

            writer.WriteEndElement(); //forwardToModule
        }
Beispiel #4
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(CustomDebugInfoRecord record)
        {
            Debug.Assert(record.Kind == CustomDebugInfoKind.UsingInfo);

            writer.WriteStartElement("using");

            ImmutableArray <short> counts = CDI.DecodeUsingRecord(record.Data);

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

            writer.WriteEndElement(); //using
        }
Beispiel #5
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 WriteStatemachineHoistedLocalScopesCustomDebugInfo(CustomDebugInfoRecord record)
        {
            Debug.Assert(record.Kind == CustomDebugInfoKind.StateMachineHoistedLocalScopes);

            writer.WriteStartElement("hoistedLocalScopes");

            var scopes = CDI.DecodeStateMachineHoistedLocalScopesRecord(record.Data);

            foreach (StateMachineHoistedLocalScope scope in scopes)
            {
                writer.WriteStartElement("slot");
                writer.WriteAttributeString("startOffset", AsILOffset(scope.StartOffset));
                writer.WriteAttributeString("endOffset", AsILOffset(scope.EndOffset));
                writer.WriteEndElement(); //bucket
            }

            writer.WriteEndElement();
        }
Beispiel #6
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(CustomDebugInfoRecord record)
        {
            writer.WriteStartElement("unknown");
            writer.WriteAttributeString("kind", record.Kind.ToString());
            writer.WriteAttributeString("version", record.Version.ToString());

            PooledStringBuilder pooled  = PooledStringBuilder.GetInstance();
            StringBuilder       builder = pooled.Builder;

            foreach (byte b in record.Data)
            {
                builder.AppendFormat("{0:X2}", b);
            }

            writer.WriteAttributeString("payload", pooled.ToStringAndFree());

            writer.WriteEndElement(); //unknown
        }
Beispiel #7
0
        private unsafe void WriteEditAndContinueLocalSlotMap(CustomDebugInfoRecord record)
        {
            Debug.Assert(record.Kind == CustomDebugInfoKind.EditAndContinueLocalSlotMap);

            writer.WriteStartElement("encLocalSlotMap");

            int syntaxOffsetBaseline = -1;

            fixed(byte *compressedSlotMapPtr = &record.Data.ToArray()[0])
            {
                var blobReader = new BlobReader(compressedSlotMapPtr, record.Data.Length);

                while (blobReader.RemainingBytes > 0)
                {
                    byte b = blobReader.ReadByte();

                    if (b == 0xff)
                    {
                        break;
                    }

                    if (b == 0xfe)
                    {
                        syntaxOffsetBaseline = -blobReader.ReadCompressedInteger();
                        writer.WriteElementString("baseline", syntaxOffsetBaseline.ToString());
                        continue;
                    }

                    writer.WriteStartElement("slot");

                    if (b == 0)
                    {
                        // short-lived temp, no info
                        writer.WriteAttributeString("kind", "temp");
                    }
                    else
                    {
                        int  synthesizedKind = (b & 0x3f) - 1;
                        bool hasOrdinal      = (b & (1 << 7)) != 0;

                        int  syntaxOffset;
                        bool badSyntaxOffset = !blobReader.TryReadCompressedInteger(out syntaxOffset);
                        syntaxOffset += syntaxOffsetBaseline;

                        int  ordinal    = 0;
                        bool badOrdinal = hasOrdinal && !blobReader.TryReadCompressedInteger(out ordinal);

                        writer.WriteAttributeString("kind", synthesizedKind.ToString());
                        writer.WriteAttributeString("offset", badSyntaxOffset ? "?" : syntaxOffset.ToString());

                        if (badOrdinal || hasOrdinal)
                        {
                            writer.WriteAttributeString("ordinal", badOrdinal ? "?" : ordinal.ToString());
                        }
                    }

                    writer.WriteEndElement();
                }
            }

            writer.WriteEndElement(); //encLocalSlotMap
        }