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); }
public LocalConstant GetLocalConstant(LocalConstantHandle handle) { return new LocalConstant(this, handle); }
internal SymConstant(SymReader symReader, LocalConstantHandle handle) { Debug.Assert(symReader != null); _symReader = symReader; _handle = handle; }
internal BlobHandle GetSignature(LocalConstantHandle handle) { int rowOffset = (handle.RowId - 1) * RowSize; return BlobHandle.FromOffset(Block.PeekHeapReference(rowOffset + _signatureOffset, _isBlobHeapRefSizeSmall)); }
internal StringHandle GetName(LocalConstantHandle handle) { int rowOffset = (handle.RowId - 1) * RowSize; return StringHandle.FromOffset(Block.PeekHeapReference(rowOffset + NameOffset, _isStringHeapRefSizeSmall)); }
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()); }
internal SymConstant(PortablePdbReader pdbReader, LocalConstantHandle handle) { Debug.Assert(pdbReader != null); _pdbReader = pdbReader; _handle = handle; }
public static LocalConstant GetLocalConstant(this LocalConstantHandle handle, MetadataReader reader) => reader.GetLocalConstant(handle);
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);
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); } }); }