Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get functionname from the functionpointer?

I have a pointer to functions like this.

TTestEvent = function(): Boolean;

procedure ExecuteTest(aTest: TTestEvent; aType: String);
begin
  if aTest then
    NotifyLog(aType + ' success')
  else
    TestError(aType + ' failed');
end;

// Call the test
procedure TestAll;
begin
  ExecuteTest(LoadParcels, 'LoadParcel');
end;

But it would be even nicer to extract the name of the function from the functionpointer aTest.

So instead of

aType + ' success'

I want something like

ExtractName(aTest) + ' success'

Can this be done in Delphi 2007 ?

like image 627
Roland Bengtsson Avatar asked Dec 27 '22 08:12

Roland Bengtsson


2 Answers

If you use some of our Open Source classes, you'll be able to find the name of any symbol.

You'll have to create a .map file when building your executable, by setting "Detailed map" in your projects option.

You can then deliver the .map with the .exe, or compress the .map into our proprietary .mab format, which can be appended to the .exe. The .mab format is just a lot more efficient than .zip or other for this task: it is about 10 times smaller than the original .map file (that is, much smaller than JCLDebug or MaxExpect offers, and very much smaller than using the standard "Remote debugging symbol" embedding project option).

Then you can use the TSynMapFile class to retrieve debugging information from the .map file, or the information embedded into the .exe:

function ExtractName(aSymbolAddress: pointer): string;
var i: integer;
begin
  with TSynMapFile.Create do // no name supplied -> will read from .exe
  try
    i := FindSymbol(aSymbolAddress);
    if i>=0 then
      result := Symbols[i].Name else
      result := '';
  finally
    Free;
  end;
end;

It will work for function names, but also any other symbols, like methods or global variables.

See this blog article about the class. And note that even if it is used by our mORMot framework, or its logging features, you just do not need to use the whole framework (just SynCommons.pas and SynLZ.pas units). See the Map2Mab.dpr program in "SQLite3\Samples\11 - Exception logging" sub folder to embed .map file content into an .exe.

like image 135
Arnaud Bouchez Avatar answered Dec 30 '22 01:12

Arnaud Bouchez


You cannot do this with built-in features. In order to get a function name from an address you need to know the map of the executable. This is not part of an executable unless you take steps to add it.

Debugging tools like JclDebug and madExcept offer the functionality you are looking for.

like image 43
David Heffernan Avatar answered Dec 30 '22 01:12

David Heffernan