static unsafe object to_object(TysosType enum_type, object value) { /* Convert value (of an integral type) to an enum of type 'enum_type' * and return its boxed value */ if (enum_type == null) { throw new ArgumentNullException("enumType"); } if (value == null) { throw new ArgumentException("value"); } /* The incoming value type 'value' is already boxed. * * We can therefore just copy its data to a new enum object */ void *value_obj = CastOperations.ReinterpretAsPointer(value); void *value_vtbl = *(void **)value_obj; int value_csize = *(int *)((byte *)value_vtbl + ClassOperations.GetVtblTypeSizeOffset()); void *ret_obj = MemoryOperations.GcMalloc(value_csize); MemoryOperations.MemCpy(ret_obj, value_obj, value_csize); void *ret_vtbl = *(void **)((byte *)CastOperations.ReinterpretAsPointer(enum_type) + ClassOperations.GetSystemTypeImplOffset()); *(void **)ret_obj = ret_vtbl; *(void **)((byte *)ret_obj + ClassOperations.GetMutexLockOffset()) = null; return(CastOperations.ReinterpretAsObject(ret_obj)); }
static unsafe void InternalSetValue(void *typedref, void *objval) { // get the type from the typed reference to see if we need to unbox the object // or store as a reference type void *et = *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceTypeOffset()); void *ptr = *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceValueOffset()); void *etextends = *(void **)((byte *)et + ClassOperations.GetVtblExtendsVtblPtrOffset()); if (etextends == OtherOperations.GetStaticObjectAddress("_Zu1L") || etextends == OtherOperations.GetStaticObjectAddress("_ZW6System4Enum")) { // this is a boxed value type. Get its size var vt_size = TysosType.GetValueTypeSize(et); // src ptr void *src = *(void **)((byte *)objval + ClassOperations.GetBoxedTypeDataOffset()); CopyMem((byte *)ptr, (byte *)src, vt_size); } else { // simply copy the reference *(void **)ptr = objval; } }
static unsafe bool Equals(void *a, void *b) { /* a is guaranteed to be a System.Enum, therefore just ensuring b * is the same type ensures b is an enum */ void *avtbl = *(void **)a; void *bvtbl = *(void **)b; if (avtbl != bvtbl) { return(false); } /* Get size of data to compare */ var tsize = *(int *)((byte *)avtbl + ClassOperations.GetVtblTypeSizeOffset()) - ClassOperations.GetBoxedTypeDataOffset(); int *adata = (int *)((byte *)a + ClassOperations.GetBoxedTypeDataOffset()); int *bdata = (int *)((byte *)b + ClassOperations.GetBoxedTypeDataOffset()); /* Use lowest common denominator of int32s for comparison (most enums are int32s) */ for (int i = 0; i < tsize; i += 4, adata++, bdata++) { if (*adata != *bdata) { return(false); } } return(true); }
static unsafe void *InternalToObject(void *typedref) { // get the type from the typed reference to see if we need to box the object // or simply return the address as a reference type void *et = *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceTypeOffset()); void *src = *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceValueOffset()); void *etextends = *(void **)((byte *)et + ClassOperations.GetVtblExtendsVtblPtrOffset()); if (etextends == OtherOperations.GetStaticObjectAddress("_Zu1L") || etextends == OtherOperations.GetStaticObjectAddress("_ZW6System4Enum")) { // this is a boxed value type. Get its size var vt_size = TysosType.GetValueTypeSize(et); // build a new boxed type var ret = MemoryOperations.GcMalloc(*(int *)((byte *)et + ClassOperations.GetVtblTypeSizeOffset())); // dst ptr var dst = (byte *)ret + ClassOperations.GetBoxedTypeDataOffset(); CopyMem(dst, (byte *)src, vt_size); return(ret); } else { // simply copy the reference return(*(void **)src); } }
static unsafe void Monitor_exit(byte *obj) { var tid = System.Threading.Thread.CurrentThread.ManagedThreadId; var mla = obj + ClassOperations.GetMutexLockOffset(); release(mla, tid); }
static unsafe void AssemblyName_nInit(byte *obj, out TysosAssembly assembly, bool forIntrospection, bool raiseResolveEvent) { string name = CastOperations.ReinterpretAsString(*(void **)(obj + ClassOperations.GetFieldOffset("_ZW19System#2EReflection12AssemblyName", "_Name"))); System.Diagnostics.Debugger.Log(0, "libsupcs", "AssemblyName_nInit(" + name + ", out TysosAssembly, bool, bool) called"); // split assembly name off from other fields int comma = name.IndexOf(','); string Name; if (comma != -1) { Name = name.Substring(0, comma); } else { Name = name; } if (Name.Equals("System.Private.CoreLib")) { Name = "mscorlib"; } *(void **)(obj + ClassOperations.GetFieldOffset("_ZW19System#2EReflection12AssemblyName", "_Name")) = CastOperations.ReinterpretAsPointer(Name); System.Diagnostics.Debugger.Log(0, "libsupcs", "AssemblyName_nInit - setting _Name to " + Name); assembly = null; }
internal static unsafe void StackTrace_GetStackFramesInternal(void *sfh, int iSkip, bool fNeedFileInfo, Exception e) { /* We set the 'reentrant' member of the stack frame helper here to prevent InitializeSourceInfo running further and set * iFrameCount to zero to prevent stack traces occuring via CoreCLR */ *(int *)((byte *)OtherOperations.GetStaticObjectAddress("_ZW20System#2EDiagnostics16StackFrameHelperS") + ClassOperations.GetStaticFieldOffset("_ZW20System#2EDiagnostics16StackFrameHelper", "t_reentrancy")) = 1; *(int *)((byte *)sfh + ClassOperations.GetFieldOffset("_ZW20System#2EDiagnostics16StackFrameHelper", "iFrameCount")) = 0; }
static unsafe void ReliableEnter(byte *obj, ref bool success) { var tid = System.Threading.Thread.CurrentThread.ManagedThreadId; var mla = obj + ClassOperations.GetMutexLockOffset(); while (try_acquire(mla, tid) != 1) { ; } success = true; }
static unsafe void *get_value(void *obj) { /* we can copy the entire enum object to an instance * of the underlying type and just change the * vtbl */ byte *enum_vtbl = *(byte **)obj; int enum_size = *(int *)(enum_vtbl + ClassOperations.GetVtblTypeSizeOffset()); void **enum_ti = *(void ***)enum_vtbl; void * ut_vtbl = *(enum_ti + 1); void *new_obj = MemoryOperations.GcMalloc(enum_size); MemoryOperations.MemCpy(new_obj, obj, enum_size); *(void **)new_obj = ut_vtbl; *(void **)((byte *)new_obj + ClassOperations.GetMutexLockOffset()) = null; return(new_obj); }
/* Build an array of a particular type */ public static unsafe T[] CreateSZArray <T>(int nitems, void *data_addr) { TysosType arrtt = (TysosType)typeof(T[]); TysosType elemtt = (TysosType)typeof(T); int elemsize; if (elemtt.IsValueType) { elemsize = elemtt.GetClassSize() - ClassOperations.GetBoxedTypeDataOffset(); } else { elemsize = OtherOperations.GetPointerSize(); } if (data_addr == null) { data_addr = MemoryOperations.GcMalloc(elemsize * nitems); } byte *ret = (byte *)MemoryOperations.GcMalloc(ArrayOperations.GetArrayClassSize() + 8); // extra space for lobounds and length array void *vtbl = *(void **)((byte *)CastOperations.ReinterpretAsPointer(arrtt) + ClassOperations.GetSystemTypeImplOffset()); *(void **)(ret + ClassOperations.GetVtblFieldOffset()) = vtbl; *(ulong *)(ret + ClassOperations.GetMutexLockOffset()) = 0; *(void **)(ret + ArrayOperations.GetElemTypeOffset()) = *(void **)((byte *)CastOperations.ReinterpretAsPointer(elemtt) + ClassOperations.GetSystemTypeImplOffset()); *(int *)(ret + ArrayOperations.GetElemSizeOffset()) = elemsize; *(void **)(ret + ArrayOperations.GetInnerArrayOffset()) = data_addr; *(void **)(ret + ArrayOperations.GetLoboundsOffset()) = ret + ArrayOperations.GetArrayClassSize(); *(void **)(ret + ArrayOperations.GetSizesOffset()) = ret + ArrayOperations.GetArrayClassSize() + 4; *(int *)(ret + ArrayOperations.GetRankOffset()) = 1; *(int *)(ret + ArrayOperations.GetArrayClassSize()) = 0; // lobounds[0] *(int *)(ret + ArrayOperations.GetArrayClassSize() + 4) = nitems; // sizes[0] return((T[])CastOperations.ReinterpretAsObject(ret)); }
static unsafe void InternalGetReference(void *arr, System.TypedReference *typedref, int ranks, int *rank_indices) { // idx = rightmost-index + 2nd-right * rightmost-size + 3rd-right * 2nd-right-size * right-size + ... // rank checking is done by System.Array members in coreclr int *lovals = *(int **)((byte *)arr + ArrayOperations.GetLoboundsOffset()); int *sizes = *(int **)((byte *)arr + ArrayOperations.GetSizesOffset()); // first get index of first rank if (rank_indices[0] > sizes[0]) { throw new IndexOutOfRangeException(); } int index = rank_indices[0] - lovals[0]; // now repeat mul rank size; add rank index; rank-1 times for (int rank = 1; rank < ranks; rank++) { if (rank_indices[rank] > sizes[rank]) { throw new IndexOutOfRangeException(); } index *= sizes[rank]; index += rank_indices[rank]; } // get pointer to actual data int et_size = *(int *)((byte *)arr + ArrayOperations.GetElemSizeOffset()); void *ptr = *(byte **)((byte *)arr + ArrayOperations.GetInnerArrayOffset()) + index * et_size; // store to the typed reference *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceValueOffset()) = ptr; *(void **)((byte *)typedref + ClassOperations.GetTypedReferenceTypeOffset()) = *(void **)((byte *)arr + ArrayOperations.GetElemTypeOffset()); }
static unsafe void *GetValueImpl(void *arr, int pos) { /* Get the element type of the array */ void *et = *(void **)((byte *)arr + ArrayOperations.GetElemTypeOffset()); /* Get a pointer to the source data */ var elem_size = *(int *)((byte *)arr + ArrayOperations.GetElemSizeOffset()); void *ia = *(void **)((byte *)arr + ArrayOperations.GetInnerArrayOffset()); void *sptr = (void *)((byte *)ia + pos * elem_size); /* Is this a value type? In which case we need to return a boxed value */ void *extends = *(void **)((byte *)et + ClassOperations.GetVtblExtendsVtblPtrOffset()); if (extends == OtherOperations.GetStaticObjectAddress("_Zu1L") || extends == OtherOperations.GetStaticObjectAddress("_ZW6System4Enum")) { /* This is a value type. We need to read the size of the element, * create a new object of the appropriate size and copy the data * into it */ byte *ret = (byte *)MemoryOperations.GcMalloc(elem_size + ClassOperations.GetBoxedTypeDataOffset()); *(void **)(ret + ClassOperations.GetVtblFieldOffset()) = et; *(ulong *)(ret + ClassOperations.GetMutexLockOffset()) = 0; /* Avoid calls to memcpy if possible */ switch (elem_size) { case 1: *(byte *)(ret + ClassOperations.GetBoxedTypeDataOffset()) = *(byte *)sptr; return(ret); case 2: *(ushort *)(ret + ClassOperations.GetBoxedTypeDataOffset()) = *(ushort *)sptr; return(ret); case 4: *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset()) = *(uint *)sptr; return(ret); case 8: if (OtherOperations.GetPointerSize() >= 8) { *(ulong *)(ret + ClassOperations.GetBoxedTypeDataOffset()) = *(ulong *)sptr; return(ret); } else { *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset()) = *(uint *)sptr; *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset() + 4) = *(uint *)((byte *)sptr + 4); return(ret); } case 16: if (OtherOperations.GetPointerSize() >= 8) { *(ulong *)(ret + ClassOperations.GetBoxedTypeDataOffset()) = *(ulong *)sptr; *(ulong *)(ret + ClassOperations.GetBoxedTypeDataOffset() + 8) = *(ulong *)((byte *)sptr + 8); return(ret); } else { *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset()) = *(uint *)sptr; *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset() + 4) = *(uint *)((byte *)sptr + 4); *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset() + 8) = *(uint *)((byte *)sptr + 8); *(uint *)(ret + ClassOperations.GetBoxedTypeDataOffset() + 12) = *(uint *)((byte *)sptr + 12); return(ret); } } /* Do data copy via memcpy */ MemoryOperations.MemCpy(ret + ClassOperations.GetBoxedTypeDataOffset(), sptr, elem_size); return(ret); } else { /* Its a reference type, so just return the pointer */ return(*(void **)sptr); } }