public static void RegisterTailCallThunk(IntPtr thunk)
        {
            NativePrimitiveEncoder encoder = new NativePrimitiveEncoder();

            if (!s_tailCallThunkSizeRegistered)
            {
                lock (Instance)
                {
                    if (!s_tailCallThunkSizeRegistered)
                    {
                        // Write out the size of thunks used by the calling convention converter
                        // Make sure that this is called only once
                        encoder.Init();
                        SerializeDataBlobTypeAndFlags(ref encoder,
                                                      SerializedDataBlobKind.StepThroughStubSize,
                                                      (byte)StepThroughStubFlags.IsTailCallStub);
                        encoder.WriteUnsigned((uint)RuntimeAugments.GetThunkSize());
                        Instance.ThreadSafeWriteBytes(encoder.GetBytes());
                        s_tailCallThunkSizeRegistered = true;
                    }
                }
            }

            encoder.Init();
            SerializeDataBlobTypeAndFlags(ref encoder,
                                          SerializedDataBlobKind.StepThroughStubAddress,
                                          (byte)StepThroughStubFlags.IsTailCallStub);
            encoder.WriteUnsignedLong((ulong)thunk.ToInt64());
            Instance.ThreadSafeWriteBytes(encoder.GetBytes());
        }
        private int Encode()
        {
            EETypeOptionalFieldsElement eLastTag = EETypeOptionalFieldsElement.Count;

            for (EETypeOptionalFieldsElement eTag = 0; eTag < EETypeOptionalFieldsElement.Count; eTag++)
            {
                eLastTag = _rgFields[(int)eTag]._fieldPresent ? eTag : eLastTag;
            }

            if (eLastTag == EETypeOptionalFieldsElement.Count)
            {
                return(0);
            }

            _encoder = new NativePrimitiveEncoder();
            _encoder.Init();

            for (EETypeOptionalFieldsElement eTag = 0; eTag < EETypeOptionalFieldsElement.Count; eTag++)
            {
                if (!_rgFields[(int)eTag]._fieldPresent)
                {
                    continue;
                }

                _encoder.WriteByte((byte)((byte)eTag | (eTag == eLastTag ? 0x80 : 0)));
                _encoder.WriteUnsigned(_rgFields[(int)eTag]._value);
            }

            return(_encoder.Size);
        }
        public static void RegisterDebugDataForMethod(TypeBuilder typeBuilder, InstantiatedMethod method)
        {
            NativePrimitiveEncoder encoder = new NativePrimitiveEncoder();

            encoder.Init();

            byte sharedMethodFlags = 0;

            sharedMethodFlags |= (byte)(method.OwningType.IsGeneric() ? SharedMethodFlags.HasDeclaringTypeHandle : 0);

            SerializeDataBlobTypeAndFlags(ref encoder, SerializedDataBlobKind.SharedMethod, sharedMethodFlags);
            encoder.WriteUnsignedLong((ulong)method.RuntimeMethodDictionary.ToInt64());
            encoder.WriteUnsigned((uint)method.Instantiation.Length);

            foreach (var instParam in method.Instantiation)
            {
                encoder.WriteUnsignedLong((ulong)typeBuilder.GetRuntimeTypeHandle(instParam).ToIntPtr().ToInt64());
            }

            if (method.OwningType.IsGeneric())
            {
                encoder.WriteUnsignedLong((ulong)typeBuilder.GetRuntimeTypeHandle(method.OwningType).ToIntPtr().ToInt64());
            }

            Instance.ThreadSafeWriteBytes(encoder.GetBytes());
        }
        /// <summary>
        /// Add information about dynamically created non-generic native format type
        /// to the diagnostic stream in form of a NativeFormatType blob.
        /// </summary>
        /// <param name="typeBuilder">TypeBuilder is used to query runtime type handle for the type</param>
        /// <param name="defType">Type to emit to the diagnostic stream</param>
        /// <param name="state"></param>
        public static void RegisterDebugDataForNativeFormatType(TypeBuilder typeBuilder, DefType defType, TypeBuilderState state)
        {
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            NativeFormatType nativeFormatType = defType as NativeFormatType;
            if (nativeFormatType == null)
            {
                return;
            }

            NativePrimitiveEncoder encoder = new NativePrimitiveEncoder();
            encoder.Init();

            byte nativeFormatTypeFlags = 0;

            SerializeDataBlobTypeAndFlags(
                ref encoder,
                SerializedDataBlobKind.NativeFormatType,
                nativeFormatTypeFlags);

            TypeManagerHandle moduleHandle = ModuleList.Instance.GetModuleForMetadataReader(nativeFormatType.MetadataReader);

            encoder.WriteUnsignedLong(unchecked ((ulong)typeBuilder.GetRuntimeTypeHandle(defType).ToIntPtr().ToInt64()));
            encoder.WriteUnsigned(nativeFormatType.Handle.ToHandle(nativeFormatType.MetadataReader).AsUInt());
            encoder.WriteUnsignedLong(unchecked ((ulong)moduleHandle.GetIntPtrUNSAFE().ToInt64()));

            Instance.ThreadSafeWriteBytes(encoder.GetBytes());
#else
            return;
#endif
        }
Beispiel #5
0
        /// <summary>
        /// From a string, get a pointer to an allocated memory location that holds a NativeFormat encoded string.
        /// This is used for the creation of RuntimeFieldHandles from metadata.
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public IntPtr GetNativeFormatStringForString(string str)
        {
            using (LockHolder.Hold(_typeLoaderLock))
            {
                IntPtr result;
                if (_nativeFormatStrings.TryGetValue(str, out result))
                {
                    return(result);
                }

                NativePrimitiveEncoder stringEncoder = new NativePrimitiveEncoder();
                stringEncoder.Init();
                byte[] utf8Bytes = Encoding.UTF8.GetBytes(str);
                stringEncoder.WriteUnsigned(checked ((uint)utf8Bytes.Length));
                foreach (byte b in utf8Bytes)
                {
                    stringEncoder.WriteByte(b);
                }

                IntPtr allocatedNativeFormatString = MemoryHelpers.AllocateMemory(stringEncoder.Size);
                unsafe
                {
                    stringEncoder.Save((byte *)allocatedNativeFormatString.ToPointer(), stringEncoder.Size);
                }
                _nativeFormatStrings.Add(str, allocatedNativeFormatString);
                return(allocatedNativeFormatString);
            }
        }
        // Helper method to serialize the data-blob type and flags
        public static void SerializeDataBlobTypeAndFlags(ref NativePrimitiveEncoder encoder, SerializedDataBlobKind blobType, byte flags)
        {
            // make sure that blobType fits in 2 bits and flags fits in 6 bits
            Debug.Assert(blobType < SerializedDataBlobKind.Limit);
            Debug.Assert((byte)blobType <= 2 && flags <= 0x3F ||
                         (byte)blobType == 3 && flags <= 1 ||
                         (byte)blobType > 3 && flags <= 7);
            byte encodedKindAndFlags;

            if (blobType <= (SerializedDataBlobKind)3)
            {
                encodedKindAndFlags = (byte)((byte)blobType | (flags << 2));
            }
            else
            {
                encodedKindAndFlags = (byte)(3 | (((byte)blobType - 3) << 3) | (flags << 5));
            }
            encoder.WriteByte(encodedKindAndFlags);
        }
        public static void RegisterDebugDataForType(TypeBuilder typeBuilder, DefType defType, TypeBuilderState state)
        {
            if (!defType.IsGeneric())
            {
                RegisterDebugDataForNativeFormatType(typeBuilder, defType, state);
                return;
            }

            if (defType.IsGenericDefinition)
            {
                // We don't yet have an encoding for open generic types
                // TODO! fill this in
                return;
            }

            NativePrimitiveEncoder encoder = new NativePrimitiveEncoder();

            encoder.Init();

            IntPtr gcStaticFieldData    = TypeLoaderEnvironment.Instance.TryGetGcStaticFieldData(typeBuilder.GetRuntimeTypeHandle(defType));
            IntPtr nonGcStaticFieldData = TypeLoaderEnvironment.Instance.TryGetNonGcStaticFieldData(typeBuilder.GetRuntimeTypeHandle(defType));

            bool isUniversalGenericType          = state.TemplateType != null && state.TemplateType.IsCanonicalSubtype(CanonicalFormKind.Universal);
            bool embeddedTypeSizeAndFieldOffsets = isUniversalGenericType || (state.TemplateType == null);
            uint instanceFieldCount = 0;
            uint staticFieldCount   = 0;

            // GetDiagnosticFields only returns the fields that are of interest for diagnostic reporting. So it doesn't
            // return a meaningful list for non-universal canonical templates
            IEnumerable <FieldDesc> diagnosticFields = defType.GetDiagnosticFields();

            foreach (var f in diagnosticFields)
            {
                if (f.IsLiteral)
                {
                    continue;
                }

                if (f.IsStatic)
                {
                    ++staticFieldCount;
                }
                else
                {
                    ++instanceFieldCount;
                }
            }

            SharedTypeFlags sharedTypeFlags = 0;

            if (gcStaticFieldData != IntPtr.Zero)
            {
                sharedTypeFlags |= SharedTypeFlags.HasGCStaticFieldRegion;
            }
            if (nonGcStaticFieldData != IntPtr.Zero)
            {
                sharedTypeFlags |= SharedTypeFlags.HasNonGCStaticFieldRegion;
            }
            if (state.ThreadDataSize != 0)
            {
                sharedTypeFlags |= SharedTypeFlags.HasThreadStaticFieldRegion;
            }
            if (embeddedTypeSizeAndFieldOffsets)
            {
                sharedTypeFlags |= SerializedDebugData.SharedTypeFlags.HasTypeSize;

                if (instanceFieldCount > 0)
                {
                    sharedTypeFlags |= SerializedDebugData.SharedTypeFlags.HasInstanceFields;
                }

                if (staticFieldCount > 0)
                {
                    sharedTypeFlags |= SerializedDebugData.SharedTypeFlags.HasStaticFields;
                }
            }

            SerializeDataBlobTypeAndFlags(ref encoder, SerializedDataBlobKind.SharedType, (byte)sharedTypeFlags);

            //
            // The order of these writes is a contract shared between the runtime and debugger engine.
            // Changes here must also be updated in the debugger reader code
            //
            encoder.WriteUnsignedLong((ulong)typeBuilder.GetRuntimeTypeHandle(defType).ToIntPtr().ToInt64());
            encoder.WriteUnsigned((uint)defType.Instantiation.Length);

            foreach (var instParam in defType.Instantiation)
            {
                encoder.WriteUnsignedLong((ulong)typeBuilder.GetRuntimeTypeHandle(instParam).ToIntPtr().ToInt64());
            }

            if (gcStaticFieldData != IntPtr.Zero)
            {
                encoder.WriteUnsignedLong((ulong)gcStaticFieldData.ToInt64());
            }

            if (nonGcStaticFieldData != IntPtr.Zero)
            {
                encoder.WriteUnsignedLong((ulong)nonGcStaticFieldData.ToInt64());
            }

            // Write the TLS offset into the native thread's TLS buffer. That index de-referenced is the thread static
            // data region for this type
            if (state.ThreadDataSize != 0)
            {
                encoder.WriteUnsigned(state.ThreadStaticOffset);
            }

            // Collect information debugger only requires for universal generics and dynamically loaded types
            if (embeddedTypeSizeAndFieldOffsets)
            {
                Debug.Assert(state.TypeSize != null);
                encoder.WriteUnsigned((uint)state.TypeSize);

                if (instanceFieldCount > 0)
                {
                    encoder.WriteUnsigned(instanceFieldCount);

                    uint i = 0;
                    foreach (FieldDesc f in diagnosticFields)
                    {
                        if (f.IsLiteral)
                        {
                            continue;
                        }
                        if (f.IsStatic)
                        {
                            continue;
                        }

                        encoder.WriteUnsigned(i);
                        encoder.WriteUnsigned((uint)f.Offset.AsInt);
                        i++;
                    }
                }

                if (staticFieldCount > 0)
                {
                    encoder.WriteUnsigned(staticFieldCount);

                    uint i = 0;
                    foreach (FieldDesc f in diagnosticFields)
                    {
                        if (f.IsLiteral)
                        {
                            continue;
                        }
                        if (!f.IsStatic)
                        {
                            continue;
                        }

                        NativeLayoutFieldDesc nlfd = f as NativeLayoutFieldDesc;
                        FieldStorage          fieldStorage;
                        if (nlfd != null)
                        {
                            // NativeLayoutFieldDesc's have the field storage information directly embedded in them
                            fieldStorage = nlfd.FieldStorage;
                        }
                        else
                        {
                            // Metadata based types do not, but the api's to get the info are available
                            if (f.IsThreadStatic)
                            {
                                fieldStorage = FieldStorage.TLSStatic;
                            }
                            else if (f.HasGCStaticBase)
                            {
                                fieldStorage = FieldStorage.GCStatic;
                            }
                            else
                            {
                                fieldStorage = FieldStorage.NonGCStatic;
                            }
                        }

                        encoder.WriteUnsigned(i);
                        encoder.WriteUnsigned((uint)fieldStorage);
                        encoder.WriteUnsigned((uint)f.Offset.AsInt);
                        i++;
                    }
                }
            }

            Instance.ThreadSafeWriteBytes(encoder.GetBytes());
        }