private void methodInsideAppDomain(IntPtr startingIntPtr) { foreach (var obj in GCEx.GetObjectsInSOH(EntityPtr.ToInstance <object>(startingIntPtr), mt => mt != 0)) { Console.WriteLine(" - object: {0}, type: {1}, size: {2}", obj.Item, obj.Item.GetType().Name, GCEx.SizeOf(obj.Item)); } }
private static unsafe bool TryGetNextInSOH(object current, Predicate <long> checker, out object nextObject) { nextObject = null; try { var offset = (int)EntityPtr.ToPointer(current); var size = SizeOf(current); offset += size; var mt = (long)*(IntPtr *)(offset + IntPtr.Size); if (size == 0 || !checker(mt)) { return(false); } //if ((long)*(IntPtr*)(offset + IntPtr.Size) == 0) return false; current = EntityPtr.ToInstance <object>((IntPtr)offset); nextObject = current; return(true); } catch { return(false); } }
/// <summary> /// Allocates memory in unmanaged memory area and fills it /// with MethodTable pointer to initialize managed class instance /// </summary> /// <returns></returns> public static T AllocInUnmanaged <T>() where T : new() { var pointer = Marshal.AllocHGlobal(SizeOf <T>()); var obj = EntityPtr.ToInstance <T>(pointer); obj.SetType <T>(); return(obj); }
/// <summary> /// Enumerates all strings in heap /// </summary> /// <param name="heapsOffset">Heap starting point</param> /// <param name="lastHeapByte">Heap last byte</param> private static void EnumerateStrings(IntPtr heapsOffset, IntPtr lastHeapByte) { var count = 0; for (long pointer = heapsOffset.ToInt64(), end = lastHeapByte.ToInt64(); pointer < end; pointer++) { if (IsString(pointer)) { var str = EntityPtr.ToInstance <string>(new IntPtr(pointer)); Console.WriteLine(str); count++; } } Console.WriteLine("Total count: {0}", count); }
public static void Main() { unsafe { var data = stackalloc int[10]; var person = EntityPtr.ToInstance <Person>((IntPtr)data); SetType <Person>(person); data[3] = 10; Console.WriteLine( $"{person.X}, {person.Y}, \n Type: {person.GetType()} \n IsValueType: {person.GetType().IsValueType}"); data[3] = 20; Console.WriteLine($"{person.X}, {person.Y}"); Console.ReadLine(); } }
public unsafe UnmanagedHeap(int capacity) { _freeSize = capacity; // Getting type size and total pool size var objectSize = GCEx.SizeOf <TPoolItem>(); _capacity = capacity; _totalSize = objectSize * capacity + capacity * IntPtr.Size * 2; _startingPointer = Marshal.AllocHGlobal(_totalSize).ToPointer(); var mTable = (MethodTableInfo *)typeof(TPoolItem).TypeHandle.Value.ToInt32(); _freeObjects = (IntPtr *)_startingPointer; _allObjects = (IntPtr *)((long)_startingPointer + IntPtr.Size * capacity); _startingPointer = (void *)((long)_startingPointer + 2 * IntPtr.Size * capacity); var pFake = typeof(Stub).GetMethod("Construct", BindingFlags.Static | BindingFlags.Public); var pCtor = _ctor = typeof(TPoolItem).GetConstructor(new [] { typeof(int) }); MethodUtil.ReplaceMethod(pCtor, pFake, skip: true); for (int i = 0; i < capacity; i++) { var handler = (IntPtr *)((long)_startingPointer + (objectSize * i)); handler[1] = (IntPtr)mTable; var obj = EntityPtr.ToInstance <object>((IntPtr)handler); var reference = (TPoolItem)obj; reference.heap = this; _allObjects[i] = (IntPtr)(handler + 1); } Reset(); }
public int SizeOf() { var total = 0; int elementsize; fixed(EntityInfo *entity = &BasicInfo) { var arr = EntityPtr.ToInstance <Array>(new IntPtr(entity)); var elementType = arr.GetType().GetElementType(); if (elementType.IsValueType) { var typecode = Type.GetTypeCode(elementType); switch (typecode) { case TypeCode.Byte: case TypeCode.SByte: case TypeCode.Boolean: elementsize = 1; break; case TypeCode.Int16: case TypeCode.UInt16: case TypeCode.Char: elementsize = 2; break; case TypeCode.Int32: case TypeCode.UInt32: case TypeCode.Single: elementsize = 4; break; case TypeCode.Int64: case TypeCode.UInt64: case TypeCode.Double: elementsize = 8; break; case TypeCode.Decimal: elementsize = 12; break; default: var info = (MethodTableInfo *)elementType.TypeHandle.Value; elementsize = info->Size - sizeof(EntityInfo); break; } } else { elementsize = IntPtr.Size; } // Header total += sizeof(EntityInfo); total += elementType.IsValueType ? 0 : 4; // MethodsTable for refTypes total += IsMultidimentional ? Dimensions * 8 : 4; } // Contents if (!IsMultidimentional) { total += (Lengthes) * elementsize; } else { var res = 1; for (int i = 1, len = Dimensions; i < len; i++) { res *= GetLength(i); } total += res * elementsize; } // align size to IntPtr if ((total & 3) != 0) total += 4 - total % 4; }
public void Register <TInterface>(string fullTypeName) { instances.Add(typeof(TInterface), EntityPtr.ToInstance <Object>(appdomain.CreateInstance(fullTypeName))); }
private static unsafe void Main() { var objects = new Dictionary <Type, int>(7000); // Get current heap ranges IntPtr managedStart, managedEnd; Console.ReadKey(); MemAccessor.GetManagedHeap(out managedStart, out managedEnd); // for each byte in virtual memory block, we trying to find strings var stopwatch = Stopwatch.StartNew(); for (IntPtr *ptr = (IntPtr *)managedStart, end = (IntPtr *)managedEnd; ptr < end; ptr++) { if (IsCorrectMethodsTable(*ptr)) { // checking next object. int size; try { size = GCEx.SizeOf((EntityInfo *)(ptr - 1)) >> 2; } catch (OverflowException) { continue; } if (ptr + size > (long *)managedEnd) { continue; } { var found = EntityPtr.ToInstance <object>((IntPtr)(ptr - 1)); RegisterObject(objects, found); var lastInChain = found; foreach (var item in GCEx.GetObjectsInSOH(found, hmt => IsCorrectMethodsTable((IntPtr)hmt))) { RegisterObject(objects, item.Item); if (!item.IsArrayItem) { lastInChain = item.Item; } } long lastRecognized = (long)EntityPtr.ToPointer(lastInChain); ptr = (IntPtr *)(lastRecognized + lastInChain.SizeOf()); } } } var timeToTakeSnapshot = stopwatch.ElapsedMilliseconds; foreach (var type in objects.Keys.OrderByDescending(key => objects[key])) { Console.WriteLine("{0:00000} : {1}", objects[type], type.FullName); } Console.WriteLine("Objects total: {0}. Time taken: {1}", objects.Values.Sum(), timeToTakeSnapshot); Console.ReadKey(); }