What are the layout and size of the managed class header in unmanaged memory?

Recently, in this question , I asked how to get the raw class memory address in C # (this is a crude unreliable hack and bad practice, do not use it if you do not need it). I succeeded, but then a problem arose: according to this article, the first 2 words in the raw memory representation of the class should be pointers to SyncBlock and RTTI, so the first address of the field should be shifted by 2 words [8 bytes on 32-bit systems, 16 bytes in 64-bit systems] from the very beginning. However, when I delete the first bytes from the memory at the location of the object, the first initial field offset from the object address is only 1 32-bit word (4 bytes), which makes no sense for both types of systems. From the question I linked:

class Program { // Here is the function. // I suggest looking at the original question solution, as it is // more reliable. static IntPtr getPointerToObject(Object unmanagedObject) { GCHandle gcHandle = GCHandle.Alloc(unmanagedObject, GCHandleType.WeakTrackResurrection); IntPtr thePointer = Marshal.ReadIntPtr(GCHandle.ToIntPtr(gcHandle)); gcHandle.Free(); return thePointer; } class TestClass { uint a = 0xDEADBEEF; } static void Main(string[] args) { byte[] cls = new byte[16]; var test = new TestClass(); var thePointer = getPointerToObject(test); Marshal.Copy(thePointer, cls, 0, 16); //Dump first 16 bytes... Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(thePointer.ToInt32()))); Console.WriteLine(BitConverter.ToString(cls)); Console.ReadLine(); gcHandle.Free(); } } /* Example output (yours should be different): 40-23-CA-02 4C-38-04-01-EF-BE-AD-DE-00-00-00-80-B4-21-50-73 That field value is "EF-BE-AD-DE", 0xDEADBEEF as it is stored in memory. Yay, we found it! */ 

Why is that? Maybe I just misunderstood the address, but how and why? And if I do not, what could be wrong? Maybe if this article is wrong, I just misunderstood what the title of a managed class looks like? Or maybe it doesn't have a Lock pointer - but why and how is this possible? ..

(These are obviously just a few possible options, and although I still carefully check each one that I can predict, wild guesses cannot compare both time and accuracy with the correct answer.)

+5
source share
1 answer

@HansPassant brilliantly pointed out that the pointer to the object in question points to the structure of the second , the method table. Now this is quite reasonable for performance reasons, since the method table (RTTI structure) is used much more often than the SyncRoot structure, which, therefore, is still located directly in front of it with a negative index of -1. He made it clear that he did not want to publish this answer, so I send it myself, but the loan still goes to him.

But I would like to remind you that this dirty unreliable hack may make the system unstable:

Besides the pinning problem, other unpleasant problems have no idea how long the object is and how the fields are organized.

Instead, you should use a debugger if you don’t understand all the consequences, understand exactly what you are trying to do, and really need to do it - using this is a dirty and unreliable way.

0
source

Source: https://habr.com/ru/post/1236341/


All Articles