Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I obtain the address of internal System.pas functions?

I'm working on a JIT compiler, and trying to figure out how to output proper cleanup blocks for managed types such as strings.

The disassembly of the cleanup block for a function that has one local variable of type string looks like this:

0044333C 648910           mov fs:[eax],edx
0044333F 6854334400       push $00443354
00443344 8D45FC           lea eax,[ebp-$04]
00443347 E81834FCFF       call @UStrClr
0044334C C3               ret 
0044334D E9062BFCFF       jmp @HandleFinally
00443352 EBF0             jmp $00443344

Unfortunately, I don't have any good way to obtain the addresses of @UStrClr and @HandleFinally so my JITter can insert them. They're declared in System.Pas as _UStrClr and _HandleFinally, in the interface section, but apparently there's some "magic" going on because trying to use those identifiers results in a compiler error.

So I tried an ASM routine, where I declared a global pointer and said mov func_ustr_clear, @UStrClear. This time I don't get an undeclared identifier error; I get something even stranger:

[DCC Error]: E2107 Operand size mismatch

So does anyone have any idea how to do this right?

like image 465
Mason Wheeler Avatar asked Jan 20 '14 03:01

Mason Wheeler


1 Answers

Try these functions to get the address of UStrClr and HandleFinally:

function GetUStrClrAddress: Pointer;
asm
{$IFDEF CPUX64}
  mov rcx, offset System.@UStrClr;
  mov @Result, rcx;
{$ELSE}
  mov @Result, offset System.@UStrClr;
{$ENDIF}
end;

function GetHandleFinallyAddress: Pointer;
asm
{$IFDEF CPUX64}
  mov rcx, offset System.@HandleFinally;
  mov @Result, rcx;
{$ELSE}
  mov @Result, offset System.@HandleFinally;
{$ENDIF}
end;

Edit:

@ArnaudBouchez also suggests some further optimization. By directly putting the value into the function return register, the function is a little faster.

function GetUStrClrAddress: Pointer; 
asm 
  {$ifdef CPU64} 
    mov rax,offset System.@UStrClr 
  {$else} 
    mov eax,offset System.@UStrClr 
  {$endif} 
end;

Further reading of the assembler use in Delphi could be found here (and the use of the OFFSET keyword), Assembly Expressions, Expression Classes.

like image 80
LU RD Avatar answered Oct 04 '22 01:10

LU RD