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 void push_ehdr(void *eh, void *fp) { if (start == null) { void **new_start = (void **)MemoryOperations.GcMalloc(stack_length * sizeof(void *)); fixed(void ***start_addr = &start) { if (OtherOperations.CompareExchange((void **)start_addr, (void *)new_start) == null) { end = start + stack_length; cur = start; System.Diagnostics.Debugger.Log(0, "libsupcs", "new ehdr stack at " + ((ulong)start).ToString("X") + "-" + ((ulong)end).ToString("X")); } } } if ((cur + 1) >= end) { System.Diagnostics.Debugger.Break(); throw new OutOfMemoryException("exception header stack overflowed"); } //if(System.Threading.Thread.CurrentThread.ManagedThreadId != 1) // System.Diagnostics.Debugger.Log(0, "libsupcs", "exceptions: push_ehdr: " + ((ulong)eh).ToString("X")); // the following should be atomic for the current stack only, so disabling interrupts is // sufficient var state = OtherOperations.EnterUninterruptibleSection(); *cur++ = eh; *cur++ = fp; OtherOperations.ExitUninterruptibleSection(state); }
internal static void leave_try(void *eh) { void *fp = PopFramePointer(); void *popped = PopEhdr(); if (eh != popped) { System.Diagnostics.Debugger.Log(0, "libsupcs", "leave_try: popping incorrect exception header"); System.Diagnostics.Debugger.Log(0, "libsupcs", "expected: " + ((ulong)eh).ToString("X")); System.Diagnostics.Debugger.Log(0, "libsupcs", "got: " + ((ulong)popped).ToString("X") + ", fp: " + ((ulong)fp).ToString("X")); System.Diagnostics.Debugger.Log(0, "libsupcs", "start: " + ((ulong)start).ToString("X")); System.Diagnostics.Debugger.Log(0, "libsupcs", "end: " + ((ulong)end).ToString("X")); System.Diagnostics.Debugger.Log(0, "libsupcs", "cur: " + ((ulong)cur).ToString("X")); System.Diagnostics.Debugger.Log(0, "libsupcs", "calling_pc: " + ((ulong)OtherOperations.GetUnwinder().UnwindOne().GetInstructionPointer()).ToString("X")); while (true) { ; } } void **ehdr = (void **)eh; int eh_type = *(int *)ehdr; if (eh_type == 2) { // handle finally clause void *handler = *(ehdr + 1); OtherOperations.CallI(fp, handler); PopFramePointer(); PopEhdr(); } }
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; } }
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; }
internal static void enter_try(void *eh, void *fp) { if (eh == PeekEhdr()) { System.Diagnostics.Debugger.Log(0, "libsupcs", "enter_try: recursive try block found from calling_pc: " + ((ulong)OtherOperations.GetUnwinder().UnwindOne().GetInstructionPointer()).ToString("X")); } PushEhdr(eh, fp); }
private static void load_mscorlib() { var str = AssemblyLoader.LoadAssembly("mscorlib"); metadata.PEFile pef = new metadata.PEFile(); var m = pef.Parse(str, AssemblyLoader); AssemblyLoader.AddToCache(m, "mscorlib"); mscorlib = m; BinaryAssemblyLoader.ptr_cache[(ulong)OtherOperations.GetStaticObjectAddress("mscorlib")] = m; }
static void *peek_ehdr() { if (start == null || (void **)cur <= (void **)start) { return(null); } var state = OtherOperations.EnterUninterruptibleSection(); var ret = *(cur - 2); OtherOperations.ExitUninterruptibleSection(state); return(ret); }
internal static int Assert_ShowDefaultAssertDialog(string conditionString, string message, string stackTrace, string windowTitle) { OtherOperations.EnterUninterruptibleSection(); System.Diagnostics.Debugger.Log(0, "Assert", windowTitle); System.Diagnostics.Debugger.Log(0, "Assert", conditionString); System.Diagnostics.Debugger.Log(0, "Assert", message); System.Diagnostics.Debugger.Log(0, "Assert", stackTrace); while (true) { ; } }
static unsafe byte InternalGetCorElementType(void *enum_obj) { var enum_type = GetUnderlyingEnumTypeVtbl(**(void ***)enum_obj); if (enum_type == OtherOperations.GetStaticObjectAddress("_Zi")) { return((byte)metadata.CorElementType.I4); } else if (enum_type == OtherOperations.GetStaticObjectAddress("_Zx")) { return((byte)metadata.CorElementType.I8); } throw new NotImplementedException(); }
static void *pop_fp() { if (start == null || cur <= start) { System.Diagnostics.Debugger.Break(); throw new OutOfMemoryException("exception header stack underflowed"); } var state = OtherOperations.EnterUninterruptibleSection(); var ret = *--cur; OtherOperations.ExitUninterruptibleSection(state); return(ret); }
static void *pop_ehdr() { if (start == null || (void **)cur <= (void **)start) { System.Diagnostics.Debugger.Break(); throw new OutOfMemoryException("exception header stack underflowed"); } var state = OtherOperations.EnterUninterruptibleSection(); var ret = *--cur; OtherOperations.ExitUninterruptibleSection(state); return(ret); //if (System.Threading.Thread.CurrentThread.ManagedThreadId != 1) // System.Diagnostics.Debugger.Log(0, "libsupcs", "exceptions: pop_ehdr: " + ((ulong)*cur).ToString("X")); }
/* 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)); }
public override DataInterface LoadAssembly(string name) { void *ptr; System.Diagnostics.Debugger.Log(0, "metadata", "Metadata.BinaryAssemblyLoader.LoadAssembly: request to load " + name); if (name == "mscorlib" || name == "mscorlib.dll") { ptr = OtherOperations.GetStaticObjectAddress("mscorlib"); } else if (name == "libsupcs" || name == "libsupcs.dll") { ptr = OtherOperations.GetStaticObjectAddress("libsupcs"); } else if (name == "metadata" || name == "metadata.dll") { ptr = OtherOperations.GetStaticObjectAddress("metadata"); } else { ptr = JitOperations.GetAddressOfObject(name); } return(new BinaryInterface(ptr)); }
static void GetExecutingAssembly(StackCrawlMarkHandle scmh, TysosModule.ObjectHandleOnStack ret) { int scm = *(int *)scmh.ptr; System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosAssembly.GetExecutingAssembly: scm: " + scm.ToString()); Unwinder u = OtherOperations.GetUnwinder(); u.UnwindOne(); u.UnwindOne(); // we are double-nested within coreclr so unwind this and calling method (GetExecutingAssembly(ref StackMarkHandle)) first switch (scm) { case 0: break; case 1: u.UnwindOne(); break; case 2: u.UnwindOne(); u.UnwindOne(); break; default: System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosAssembly.GetExecutingAssembly: unsupported scm: " + scm.ToString()); throw new NotSupportedException(); } System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosAssembly.GetExecutingAssembly: requested pc " + ((ulong)u.GetInstructionPointer()).ToString("X")); void *offset; var name = JitOperations.GetNameOfAddress((void *)u.GetInstructionPointer(), out offset); if (name == null) { System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosAssembly.GetExecutingAssembly: symbol not found"); *ret.ptr = null; return; } System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosAssembly.GetExecutingAssembly: found method " + name); var ts = Metadata.MSCorlib.DemangleObject(name); if (ts == null) { System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosAssembly.GetExecutingAssembly: demangler returned null"); *ret.ptr = null; return; } var m = ts.Metadata; if (m == null) { System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosAssembly.GetExecutingAssembly: returned ts had no assembly"); *ret.ptr = null; return; } var aptr = (m.file as Metadata.BinaryInterface).b; var retm = TysosModule.GetModule(aptr, m.AssemblyName); System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosAssembly.GetExecutingAssembly: returning " + retm.ass.assemblyName); *ret.ptr = CastOperations.ReinterpretAsPointer(retm.ass); }
public override object Invoke(object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, object[] parameters, System.Globalization.CultureInfo culture) { uint flags = 0; if (MethodAddress == null) { var mangled_name = mspec.MangleMethod(); System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosMethod.Invoke: requesting run-time address for " + mangled_name); MethodAddress = JitOperations.GetAddressOfObject(mspec.MangleMethod()); if (MethodAddress == null) { System.Diagnostics.Debugger.Log(0, "libsupcs", "TysosMethod.Invoke: jit compiling method"); MethodAddress = JitOperations.JitCompile(this.mspec); } } if (MethodAddress == null) { throw new System.Reflection.TargetException("Method does not have a defined implementation (" + OwningType.FullName + "." + Name + "())"); } if (!IsStatic && (obj == null)) { throw new System.Reflection.TargetException("Instance method and obj is null (" + OwningType.FullName + "." + Name + "())"); } // TODO: check number and type of parameters is what the method expects // Get total number of parameters int p_length = 0; if (parameters != null) { p_length = parameters.Length; } if (!IsStatic) { p_length++; } // See InternalStrCpy for the rationale here int max_stack_alloc = p_length > 512 ? 512 : p_length; IntPtr *pstack = stackalloc IntPtr[max_stack_alloc]; IntPtr *tstack = stackalloc IntPtr[max_stack_alloc]; void **ps, ts; if (max_stack_alloc <= 512) { ps = (void **)pstack; ts = (void **)tstack; } else { ps = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *)); ts = (void **)MemoryOperations.GcMalloc(p_length * sizeof(void *)); } // Build a new params array to include obj if necessary, and a tysos type array int curptr = 0; if (!IsStatic) { ps[0] = CastOperations.ReinterpretAsPointer(obj); ts[0] = OtherOperations.GetStaticObjectAddress("_Zu1O"); curptr++; } if (parameters != null) { for (int i = 0; i < parameters.Length; i++, curptr++) { var cp = CastOperations.ReinterpretAsPointer(parameters[i]); ps[curptr] = cp; ts[curptr] = *(void **)cp; } } if (!IsStatic) { flags |= invoke_flag_instance; } if (OwningType.IsValueType) { flags |= invoke_flag_vt; } if (ReturnType != null && ReturnType.IsValueType) { flags |= invoke_flag_vt_ret; } return(CastOperations.ReinterpretAsObject(InternalInvoke(MethodAddress, p_length, ps, ts, (ReturnType != null) ? TysosType.ReinterpretAsType(ReturnType)._impl : null, flags))); }
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); } }