What is the "identification pointer" before TTypeInfo?

If you navigate quite a lot in the internal components of Delphi, you will find something strange and apparently undocumented by the TTypeInfo entries generated by the compiler. If PTypeInfo points to a TTypeInfo entry at address X, in X - 4 you will find that the following 4 bytes describe a pointer to X. For example:

 procedure test(info: PTypeInfo); var addr: cardinal; ptr: PPointer; begin addr := cardinal(info); writeln('addr: ', addr); dec(addr, 4); ptr := PPointer(addr); addr := cardinal(ptr^); writeln('addr: ', addr); end; 

Pass any legitimate PTypeInfo generated by the compiler to this procedure, and it will output the same address twice. I searched a bit in TypInfo.pas, but I donโ€™t see anything that this โ€œidentity pointerโ€ mentions or what it is for. Does anyone know why this is happening? This is apparently true in every version of Delphi, at least from D3 to D2010.

+7
pointers rtti internals delphi
source share
3 answers

It is very simple: packages and dynamic linking.

BPLs are DLLs. DLLs are linked through tables that are being repaired, and not all the code in the EXE or DLL associated with the processed DLL (which will do great harm to read-only memory sharing between multiple processes). To prevent the need for a reference to TypeInfo(SomeType) somewhere in the code or typeinfo from an EXE or DLL, when changing a link to a BPL, there is an indirect binding to the import table instead.

It is easy to see the difference when linking statically with BPL binding in this program:

 {$apptype console} uses TypInfo, SysUtils; type TFoo = class(TObject); var x: PPTypeInfo; begin x := GetTypeData(TypeInfo(TFoo))^.ParentInfo; Writeln(x^^.Name); Writeln(Format('x %p', [x])); Writeln(Format('x^ %p', [x^])); end. 

On my local machine compiled with dcc32 test.pas , it produces:

 TObject x 00401B64 x^ 00401B68 

But when compiled with the RTL package with dcc32 -LUrtl test.pas , it produces:

 TObject x 004051F0 x^ 40001DA4 

Hope this clears it.

+10
source share

Don't fully understand what is happening, but when you look at IsPublishedProp in TypInfo , you will see that it defines the ClassInfo of the instance as a pointer to the TypeInfo structure:

 PTypeInfo(Instance.ClassInfo) 

When you look at the ClassInfo method, it returns a simple pointer whose value is similar to the vmt table:

  Result := PPointer(Integer(Self) + vmtTypeInfo)^; 

vmtTypeInfo has a value of -72. Four bytes before that at -76 is equal to vmtInitTable . VmtTypeInfo is followed by FieldTable, MethodTable, DynamicTable, etc.

The value vmtInitTable is used, for example, in TObject.CleanupInstance and passed to _FinalizeRecord as a pointer to the TypeInfo structure.

Thus, the four bytes in front of the TypeInfo structure, pointing to the TypeInfo structure, seem to exist by design and part of the vmt structure.

Edit

As Mason rightly pointed out, this is a complete red herring (see comments). I leave the answer so that others do not have to chase him.

Update To avoid confusion over the variables and their addresses, I rewrote the Mason testing procedure as follows:

 procedure test(info: PTypeInfo); begin writeln('value of info : ', cardinal(info)); writeln('info - 4 : ', cardinal(info) - 4); writeln('value 4 bytes before: ', cardinal(PPointer(cardinal(info)-4)^)); end; 

and call it the following information:

 procedure TryRTTIStuff; begin writeln('TPersistent'); test(TypeInfo(TPersistent)); writeln('TTypeKind enumeration'); test(TypeInfo(TTypeKind)); writeln('Integer'); test(TypeInfo(Integer)); writeln('Nonsense'); test(PTypeInfo($420000)); end; 

The first three give the results that Mason describes. I added only an additional file to show the pointer value for the last writeln file. The last call to TryRTTIStuff should show that when you do not pass a pointer to a valid TypeInfo structure, you will not get the same value in the first and third scripts for the call.

There is no clue as to what is happening with TypeInfo. Maybe we should ask Barry Kelly, as he is the author of the new D2010 RTTI, so he should know a lot about the old, as well ...

+1
source share

there may be a linked list that is in contiguous memory :)

0
source share

All Articles