Beispiel #1
0
        internal LocalConstant(MetadataReader reader, LocalConstantHandle handle)
        {
            Debug.Assert(reader != null);
            Debug.Assert(!handle.IsNil);

            _reader = reader;
            _rowId = handle.RowId;
        }
 public LocalConstantEntry(PEFile module, MetadataReader metadata, bool isEmbedded, LocalConstantHandle handle)
 {
     this.offset = isEmbedded ? null : (int?)metadata.GetTableMetadataOffset(TableIndex.LocalConstant)
                   + metadata.GetTableRowSize(TableIndex.LocalConstant) * (MetadataTokens.GetRowNumber(handle) - 1);
     this.module     = module;
     this.metadata   = metadata;
     this.handle     = handle;
     this.localConst = metadata.GetLocalConstant(handle);
 }
        private void SerializeMethodDebugInfo(IMethodBody bodyOpt, int methodRid, StandaloneSignatureHandle localSignatureHandleOpt, ref LocalVariableHandle lastLocalVariableHandle, ref LocalConstantHandle lastLocalConstantHandle)
        {
            if (bodyOpt == null)
            {
                _debugMetadataOpt.AddMethodDebugInformation(default(DocumentHandle), default(BlobHandle));
                return;
            }

            bool isIterator    = bodyOpt.StateMachineTypeName != null;
            bool emitDebugInfo = isIterator || bodyOpt.HasAnySequencePoints;

            if (!emitDebugInfo)
            {
                _debugMetadataOpt.AddMethodDebugInformation(default(DocumentHandle), default(BlobHandle));
                return;
            }

            var methodHandle = MetadataTokens.MethodDefinitionHandle(methodRid);

            var bodyImportScope   = bodyOpt.ImportScope;
            var importScopeHandle = (bodyImportScope != null) ? GetImportScopeIndex(bodyImportScope, _scopeIndex) : default(ImportScopeHandle);

            // documents & sequence points:
            DocumentHandle singleDocumentHandle;
            ArrayBuilder <Cci.SequencePoint> sequencePoints = ArrayBuilder <Cci.SequencePoint> .GetInstance();

            bodyOpt.GetSequencePoints(sequencePoints);
            BlobHandle sequencePointsBlob = SerializeSequencePoints(localSignatureHandleOpt, sequencePoints.ToImmutableAndFree(), _documentIndex, out singleDocumentHandle);

            _debugMetadataOpt.AddMethodDebugInformation(document: singleDocumentHandle, sequencePoints: sequencePointsBlob);

            // Unlike native PDB we don't emit an empty root scope.
            // scopes are already ordered by StartOffset ascending then by EndOffset descending (the longest scope first).

            if (bodyOpt.LocalScopes.Length == 0)
            {
                // TODO: the compiler should produce a scope for each debuggable method
                _debugMetadataOpt.AddLocalScope(
                    method: methodHandle,
                    importScope: importScopeHandle,
                    variableList: NextHandle(lastLocalVariableHandle),
                    constantList: NextHandle(lastLocalConstantHandle),
                    startOffset: 0,
                    length: bodyOpt.IL.Length);
            }
            else
            {
                foreach (LocalScope scope in bodyOpt.LocalScopes)
                {
                    _debugMetadataOpt.AddLocalScope(
                        method: methodHandle,
                        importScope: importScopeHandle,
                        variableList: NextHandle(lastLocalVariableHandle),
                        constantList: NextHandle(lastLocalConstantHandle),
                        startOffset: scope.StartOffset,
                        length: scope.Length);

                    foreach (ILocalDefinition local in scope.Variables)
                    {
                        Debug.Assert(local.SlotIndex >= 0);

                        lastLocalVariableHandle = _debugMetadataOpt.AddLocalVariable(
                            attributes: local.PdbAttributes,
                            index: local.SlotIndex,
                            name: _debugMetadataOpt.GetOrAddString(local.Name));

                        SerializeLocalInfo(local, lastLocalVariableHandle);
                    }

                    foreach (ILocalDefinition constant in scope.Constants)
                    {
                        var mdConstant = constant.CompileTimeValue;
                        Debug.Assert(mdConstant != null);

                        lastLocalConstantHandle = _debugMetadataOpt.AddLocalConstant(
                            name: _debugMetadataOpt.GetOrAddString(constant.Name),
                            signature: SerializeLocalConstantSignature(constant));

                        SerializeLocalInfo(constant, lastLocalConstantHandle);
                    }
                }
            }

            var asyncDebugInfo = bodyOpt.AsyncDebugInfo;

            if (asyncDebugInfo != null)
            {
                _debugMetadataOpt.AddStateMachineMethod(
                    moveNextMethod: methodHandle,
                    kickoffMethod: GetMethodDefinitionHandle(asyncDebugInfo.KickoffMethod));

                SerializeAsyncMethodSteppingInfo(asyncDebugInfo, methodHandle);
            }

            SerializeStateMachineLocalScopes(bodyOpt, methodHandle);

            // delta doesn't need this information - we use information recorded by previous generation emit
            if (Context.Module.CommonCompilation.Options.EnableEditAndContinue && !IsFullMetadata)
            {
                SerializeEncMethodDebugInformation(bodyOpt, methodHandle);
            }
        }
 private static LocalConstantHandle NextHandle(LocalConstantHandle handle) =>
 MetadataTokens.LocalConstantHandle(MetadataTokens.GetRowNumber(handle) + 1);
        private static void SerializeScope(
            MetadataBuilder metadataBuilder,
            MetadataModel metadataModel,
            MethodDefinitionHandle methodHandle,
            ImportScopeHandle importScopeHandle,
            ISymUnmanagedScope symScope,
            Dictionary <int, DynamicLocalInfo> dynamicSlots,
            Dictionary <string, DynamicLocalInfo> dynamicNames,
            bool vbSemantics,
            ref LocalVariableHandle lastLocalVariableHandle,
            ref LocalConstantHandle lastLocalConstantHandle)
        {
            // VB Windows PDB encode the range as end-inclusive,
            // all Portable PDBs use end-exclusive encoding.
            int start = symScope.GetStartOffset();
            int end   = symScope.GetEndOffset() + (vbSemantics ? 1 : 0);

            metadataBuilder.AddLocalScope(
                method: methodHandle,
                importScope: importScopeHandle,
                variableList: NextHandle(lastLocalVariableHandle),
                constantList: NextHandle(lastLocalConstantHandle),
                startOffset: start,
                length: end - start);

            foreach (var symLocal in symScope.GetLocals())
            {
                int    slot = symLocal.GetSlot();
                string name = symLocal.GetName();

                lastLocalVariableHandle = metadataBuilder.AddLocalVariable(
                    attributes: (LocalVariableAttributes)symLocal.GetAttributes(),
                    index: slot,
                    name: metadataBuilder.GetOrAddString(name));

                DynamicLocalInfo dynamicInfo;
                if (slot > 0 && dynamicSlots.TryGetValue(slot, out dynamicInfo) ||
                    slot == 0 && dynamicNames.TryGetValue(name, out dynamicInfo))
                {
                    metadataBuilder.AddCustomDebugInformation(
                        parent: lastLocalVariableHandle,
                        kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.DynamicLocalVariables),
                        value: SerializeDynamicLocalBlob(metadataBuilder, dynamicInfo));
                }
            }

            foreach (var symConstant in symScope.GetConstants())
            {
                string name  = symConstant.GetName();
                object value = symConstant.GetValue();

                lastLocalConstantHandle = metadataBuilder.AddLocalConstant(
                    name: metadataBuilder.GetOrAddString(name),
                    signature: SerializeConstantSignature(metadataBuilder, metadataModel, symConstant.GetSignature(), value));

                DynamicLocalInfo dynamicInfo;
                if (dynamicNames.TryGetValue(name, out dynamicInfo))
                {
                    metadataBuilder.AddCustomDebugInformation(
                        parent: lastLocalConstantHandle,
                        kind: metadataBuilder.GetOrAddGuid(PortableCustomDebugInfoKinds.DynamicLocalVariables),
                        value: SerializeDynamicLocalBlob(metadataBuilder, dynamicInfo));
                }
            }

            int previousChildScopeEnd = start;

            foreach (ISymUnmanagedScope child in symScope.GetChildren())
            {
                int childScopeStart = child.GetStartOffset();
                int childScopeEnd   = child.GetEndOffset();

                // scopes are properly nested:
                if (childScopeStart < previousChildScopeEnd || childScopeEnd > end)
                {
                    // TODO: loc/warning
                    throw new BadImageFormatException($"Invalid scope IL offset range: [{childScopeStart}, {childScopeEnd}), method 0x{MetadataTokens.GetToken(methodHandle):x}.");
                }

                previousChildScopeEnd = childScopeEnd;

                SerializeScope(metadataBuilder, metadataModel, methodHandle, importScopeHandle, child, dynamicSlots, dynamicNames, vbSemantics, ref lastLocalVariableHandle, ref lastLocalConstantHandle);
            }
        }
        public LocalScopeHandle AddLocalScope(MethodDefinitionHandle method, ImportScopeHandle importScope, LocalVariableHandle variableList, LocalConstantHandle constantList, int startOffset, int length)
        {
            _localScopeTable.Add(new LocalScopeRow
            {
                Method = (uint)MetadataTokens.GetRowNumber(method),
                ImportScope = (uint)MetadataTokens.GetRowNumber(importScope),
                VariableList = (uint)MetadataTokens.GetRowNumber(variableList),
                ConstantList = (uint)MetadataTokens.GetRowNumber(constantList),
                StartOffset = (uint)startOffset,
                Length = (uint)length
            });

            return MetadataTokens.LocalScopeHandle(_localScopeTable.Count);
        }
Beispiel #7
0
 public LocalConstant GetLocalConstant(LocalConstantHandle handle)
 {
     return new LocalConstant(this, handle);
 }
Beispiel #8
0
 internal SymConstant(SymReader symReader, LocalConstantHandle handle)
 {
     Debug.Assert(symReader != null);
     _symReader = symReader;
     _handle    = handle;
 }
Beispiel #9
0
 internal BlobHandle GetSignature(LocalConstantHandle handle)
 {
     int rowOffset = (handle.RowId - 1) * RowSize;
     return BlobHandle.FromOffset(Block.PeekHeapReference(rowOffset + _signatureOffset, _isBlobHeapRefSizeSmall));
 }
Beispiel #10
0
 internal StringHandle GetName(LocalConstantHandle handle)
 {
     int rowOffset = (handle.RowId - 1) * RowSize;
     return StringHandle.FromOffset(Block.PeekHeapReference(rowOffset + NameOffset, _isStringHeapRefSizeSmall));
 }
 internal SymConstant(SymReader symReader, LocalConstantHandle handle)
 {
     Debug.Assert(symReader != null);
     _symReader = symReader;
     _handle = handle;
 }
        public static (object? Value, byte[] Signature) GetConstantValueAndSignature(MetadataReader mdReader, LocalConstantHandle handle, Func<EntityHandle, string?> getQualifiedTypeName)
        {
            var constant = mdReader.GetLocalConstant(handle);

            var sigReader = mdReader.GetBlobReader(constant.Signature);
            var sigWriter = new BlobWriter(sigReader.Length);

            // custom modifiers:
            int rawTypeCode;
            while (true)
            {
                rawTypeCode = sigReader.ReadCompressedInteger();
                if (rawTypeCode == (int)SignatureTypeCode.OptionalModifier || rawTypeCode == (int)SignatureTypeCode.RequiredModifier)
                {
                    sigReader.ReadCompressedInteger();
                }
                else
                {
                    break;
                }
            }

            int customModifiersLength = sigReader.Offset - 1;
            if (customModifiersLength > 0)
            {
                sigWriter.Write(mdReader.GetBlobBytes(constant.Signature), 0, customModifiersLength);
            }

            object? translatedValue;
            if (rawTypeCode == (int)MetadataUtilities.SignatureTypeCode_ValueType ||
                rawTypeCode == (int)MetadataUtilities.SignatureTypeCode_Class)
            {
                var typeHandle = sigReader.ReadTypeHandle();

                string? qualifiedName = getQualifiedTypeName(typeHandle);
                if (qualifiedName == "System.Decimal")
                {
                    translatedValue = sigReader.ReadDecimal();
                }
                else if (qualifiedName == "System.DateTime")
                {
                    translatedValue = BitConverter.Int64BitsToDouble(sigReader.ReadDateTime().Ticks);
                }
                else if (sigReader.RemainingBytes == 0)
                {
                    // null reference is returned as a boxed integer 0:
                    translatedValue = s_nullReferenceValue;
                }
                else
                {
                    // unknown (not produced by C# or VB)
                    translatedValue = null;
                }

                sigWriter.Write((byte)rawTypeCode);
                sigWriter.WriteCompressedInteger(MetadataUtilities.GetTypeDefOrRefOrSpecCodedIndex(typeHandle));
            }
            else
            {
                bool isEnumTypeCode;
                translatedValue = ReadAndTranslateValue(ref sigReader, (SignatureTypeCode)rawTypeCode, out isEnumTypeCode);

                if (sigReader.RemainingBytes == 0)
                {
                    // primitive type code:
                    sigWriter.Write((byte)rawTypeCode);
                }
                else if (isEnumTypeCode)
                {
                    var enumTypeHandle = sigReader.ReadTypeHandle();

                    // enum type signature:
                    sigWriter.Write((byte)MetadataUtilities.SignatureTypeCode_ValueType);
                    sigWriter.WriteCompressedInteger(MetadataUtilities.GetTypeDefOrRefOrSpecCodedIndex(enumTypeHandle));
                }

                if (sigReader.RemainingBytes > 0)
                {
                    throw new BadImageFormatException();
                }
            }

            return (translatedValue, sigWriter.ToArray());
        }
Beispiel #13
0
 internal SymConstant(PortablePdbReader pdbReader, LocalConstantHandle handle)
 {
     Debug.Assert(pdbReader != null);
     _pdbReader = pdbReader;
     _handle    = handle;
 }
Beispiel #14
0
 public static LocalConstant GetLocalConstant(this LocalConstantHandle handle, MetadataReader reader) => reader.GetLocalConstant(handle);
Beispiel #15
0
        internal StringHandle GetName(LocalConstantHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;

            return(StringHandle.FromOffset(Block.PeekHeapReference(rowOffset + NameOffset, _isStringHeapRefSizeSmall)));
        }
 private void SerializeMethodDebugInfo(IMethodBody bodyOpt, int methodRid, int aggregateMethodRid, StandaloneSignatureHandle localSignatureHandleOpt, ref LocalVariableHandle lastLocalVariableHandle, ref LocalConstantHandle lastLocalConstantHandle)
 {
     if (bodyOpt == null)
     {
         _debugMetadataOpt.AddMethodDebugInformation(document: default, sequencePoints: default);
Beispiel #17
0
        internal BlobHandle GetSignature(LocalConstantHandle handle)
        {
            int rowOffset = (handle.RowId - 1) * RowSize;

            return(BlobHandle.FromOffset(Block.PeekHeapReference(rowOffset + _signatureOffset, _isBlobHeapRefSizeSmall)));
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="PdbLocalConstant"/> class.
        /// </summary>
        /// <param name="localScope">Local scope where this contanst is defined.</param>
        /// <param name="handle">Our metadata reader handle.</param>
        internal PdbLocalConstant(PdbLocalScope localScope, LocalConstantHandle handle)
        {
            LocalScope         = localScope;
            localConstantCache = SimpleCache.CreateStruct(() => LocalScope.Function.PdbFile.Reader.GetLocalConstant(handle));
            nameCache          = SimpleCache.CreateStruct(() => LocalScope.Function.PdbFile.Reader.GetString(LocalConstant.Name));
            valueCache         = SimpleCache.CreateStruct <object>(() =>
            {
                var reader = LocalScope.Function.PdbFile.Reader.GetBlobReader(LocalConstant.Signature);
                SignatureTypeCode typeCode;

                while (true)
                {
                    typeCode = reader.ReadSignatureTypeCode();
                    if (typeCode == SignatureTypeCode.OptionalModifier || typeCode == SignatureTypeCode.RequiredModifier)
                    {
                        reader.ReadCompressedInteger();
                    }
                    else
                    {
                        break;
                    }
                }

                switch (typeCode)
                {
                case SignatureTypeCode.Boolean:
                    return((short)(reader.ReadBoolean() ? 1 : 0));

                case SignatureTypeCode.Char:
                    return(reader.ReadChar());

                case SignatureTypeCode.SByte:
                    return(reader.ReadSByte());

                case SignatureTypeCode.Byte:
                    return(reader.ReadByte());

                case SignatureTypeCode.Int16:
                    return(reader.ReadInt16());

                case SignatureTypeCode.UInt16:
                    return(reader.ReadUInt16());

                case SignatureTypeCode.Int32:
                    return(reader.ReadInt32());

                case SignatureTypeCode.UInt32:
                    return(reader.ReadUInt32());

                case SignatureTypeCode.Int64:
                    return(reader.ReadInt64());

                case SignatureTypeCode.UInt64:
                    return(reader.ReadUInt64());

                case SignatureTypeCode.Single:
                    return(reader.ReadSingle());

                case SignatureTypeCode.Double:
                    return(reader.ReadDouble());

                case SignatureTypeCode.String:
                    if (reader.RemainingBytes == 1)
                    {
                        if (reader.ReadByte() != 0xFF)
                        {
                            throw new Exception("Unexpected string constant");
                        }
                        return(null);
                    }
                    if (reader.RemainingBytes % 2 != 0)
                    {
                        throw new Exception("Unexpected string constant");
                    }
                    return(reader.ReadUTF16(reader.RemainingBytes));

                case SignatureTypeCode.TypeHandle:
                case SignatureTypeCode.Object:
                default:
                    // We don't know how to parse value
                    return(null);
                }
            });
        }