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 }
/// <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()); }