2
votes

I'm building a logging system, So I'm using the JclDebug unit to obtain stack info like the name of the current caller procedure or function using the ProcByLevel function. But now I like to obtain the address (Pointer) of the caller TObject (when applies).

I want to write a function which passing the pointer of the caller method can return a instance to TObject which contains such method. like so

function GetCallerObject(CallerMethodAddress: Pointer) : TObject;
begin
  //here I'm lost
end;

See this code

{$APPTYPE CONSOLE}

{$R *.res}

uses
  Windows,
  JCLDebug,
  SysUtils;

Type
  TFooClass=class
  public
    procedure methodCaller;
  end;

procedure Show;
var
  s : string;
  i : Integer;
  LocationInfo : TJclLocationInfo;
begin
  Writeln('show');
  //values for the levels are harcoded for this sample
  LocationInfo:=GetLocationInfo(Caller(1));
  Writeln(ProcByLevel(1)+' '+Format('Caller %s %p',[LocationInfo.ProcedureName, LocationInfo.Address ]));
  //here I want get the address of TFooClass class which calls this method (Show)
   Writeln(GetCallerObject(LocationInfo.Address).ClassName); //this must return TFooClass
end;

procedure TFooClass.MethodCaller;
begin
  Writeln(Format('Self %p',[Pointer(Self)]));
  Writeln(Format('Real Caller Address %p',[Caller(0)]));
  show;
end;


var
  M : TFooClass;
begin
  try
      M:=TFooClass.Create;
      try
        M.methodCaller;
      finally
        M.Free;
      end;
      Readln;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

With the above code I'm getting some address, but none match with the address of the caller object (Self of TFooClass), I really read the full code of the JclDebug unit , but i not found any reference to the caller object, only can be retrieved the stack names which includes the class name what i'm looking for, So that make think which must be possible return the address of the caller TObject as well, but now I'm really lost.

So, how I can get the address of the caller TObject from a method using JclDebug?

1

1 Answers

3
votes

This information is, in general, not available for the following reasons:

  1. The function call you are picking off the call stack may not be a method. In other words, there may be no Self.
  2. Even if it is a method, the Self reference may not be retrievable at this point. Remember that Self is just a parameter, usually passed in eax or rax. And the contents of that register may well have changed by the time your code runs.