Where can I find information on the structure of the Delphi VMT?

4.2k views Asked by At

The System.pas file contains a fair amount of information on hard-coded VMT offsets, but it doesn't seem to actually say much about the structure of the VMT itself. What I'd really like to know is, is there any way to find out the size of a VMT at runtime, or in other words, how many virtual methods exist for a given class?

5

There are 5 answers

11
Allen Bauer On BEST ANSWER

What about the VMT structure are you wanting to know? You also do know that it is an internal implementation detail that is subject to change (and has changed over time).

To answer your specific question, here is a simple way to find the number of virtual methods for a given class:

function GetVirtualMethodCount(AClass: TClass): Integer;
begin
  Result := (PInteger(Integer(AClass) + vmtClassName)^ - 
    (Integer(AClass) + vmtParent) - SizeOf(Pointer)) div SizeOf(Pointer);
end;

This works because I happen to know that the string representing the class name is placed immediately following all the virtual method vectors in the VMT.

I also know that there are 11 virtual methods (for D2009, 9 for D2007 and prior) on all TObjects that are negatively offset from the VMT pointer itself.

That is the reason for the vmtParent reference.

Finally, by using a TClass class reference, you can pass any TObject derived class into this function and get the number of virtual methods.

1
Rob Kennedy On

I'll plug my own site for this one:

What is the virtual-method table?

It's accurate as of Delphi 2005, I think.

The VMT does not have any value giving the number of virtual-method pointers it holds. Nothing but the compiler needs to know that information, so there's no reason to record it for use at run time.

0
Jim McKeeth On

I was pretty sure Hallvard had something on the VMT. Sure enough, he has Hack #8: Explicit VMT calls which references Ray Lischner Secrets of Delphi 2 and Delphi in a Nutshell.

Here is his hacked up version of the VMT

type
  PClass = ^TClass;
  PSafeCallException = function  (Self: TObject; ExceptObject:
    TObject; ExceptAddr: Pointer): HResult;
  PAfterConstruction = procedure (Self: TObject);
  PBeforeDestruction = procedure (Self: TObject);
  PDispatch          = procedure (Self: TObject; var Message);
  PDefaultHandler    = procedure (Self: TObject; var Message);
  PNewInstance       = function  (Self: TClass) : TObject;
  PFreeInstance      = procedure (Self: TObject);
  PDestroy           = procedure (Self: TObject; OuterMost: ShortInt);
  PVmt = ^TVmt;
  TVmt = packed record
    SelfPtr           : TClass;
    IntfTable         : Pointer;
    AutoTable         : Pointer;
    InitTable         : Pointer;
    TypeInfo          : Pointer;
    FieldTable        : Pointer;
    MethodTable       : Pointer;
    DynamicTable      : Pointer;
    ClassName         : PShortString;
    InstanceSize      : PLongint;
    Parent            : PClass;
    SafeCallException : PSafeCallException;
    AfterConstruction : PAfterConstruction;
    BeforeDestruction : PBeforeDestruction;
    Dispatch          : PDispatch;
    DefaultHandler    : PDefaultHandler;
    NewInstance       : PNewInstance;
    FreeInstance      : PFreeInstance;
    Destroy           : PDestroy;
   {UserDefinedVirtuals: array[0..999] of procedure;}
  end;

You will need to read his article for more on the hack though.

1
Uli Gerhardt On

Googling :-P for "delphi vmt" yields this. Maybe this gives you a start.

0
avar On

i remember there was some information about delphi vmt in "delphi in a nutshell" book. u can start from delphi in a nutshell chapter 2 or this