пятница, 2 декабря 2016 г.

#1321. Только код. Заготовочка для заглушек для вызова локальных функций под Win64

program Lambda;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils;

function GetRBP: Pointer; assembler;
asm
   .NOFRAME
   mov rax, rbp // - тут получаем текущую базу локальных переменных
//   ret
//   mov r8, rdx
//   mov rdx, rcx
//   mov rbp, [RIP+0]
//   jmp [RIP+0]
//   mov rcx, $ffffffffffffffff
end;

function l3LocalStubPrim(aRBP: Pointer; anAction: Pointer): Pointer;
{$WriteableConst On}
const
 StubCode : array [0 .. 29 + 8] of Byte = (
  $49, $89, $D0, // mov r8, edx // - у глобальной процедуры параметры передаются через ecx, edx
  $48, $89, $CA, // mov edx, ecx // а у локальной через edx, r8
  $48, $B9, // mov rcx, 0000000000000000 // - в rcx - база
  $00, $00, $00, $00, $00, $00, $00, $00,
  $FF, $25, $00, $00, $00, $00, // jmp [RIP+0] // - тут переход на anAction
  $00, $00, $00, $00, $00, $00, $00, $00

  , $00, $00, $00, $00, $00, $00, $00, $00
 ); // StubCode
begin
 Move(aRBP, StubCode[8], SizeOf(aRBP)); // - конкретное значение rbp
 Move(anAction, StubCode[22], SizeOf(anAction)); // - конкретное значение anAction
 Result := @StubCode;
end;

function l3LocalStub(anAction: Pointer): Pointer; assembler;
asm
   .NOFRAME
   call GetRBP
   mov rdx, rcx
   mov rcx, rax
   jmp l3LocalStubPrim
   //call l3LocalStubPrim
end;

type
 TProc1 = procedure (A: Integer);
 TProc2 = procedure (A: Integer; B: Integer);

procedure Call1(aProc: TProc1);
begin
 aProc(12345);
end;

procedure Call2(aProc: TProc2);
begin
 aProc(12345, 789);
end;

procedure Test;

var
 l_S : String;

 procedure Local1(aStr: Integer);
 var
  l_S1 : String;
  l_S2 : String;
 begin
  l_S1 := 'YYY';
  l_S2 := l_S + l_S1;
  l_S2 := l_S2 + IntToStr(aStr);
  WriteLn(l_S2);
 end;

 procedure Local2(A: Integer; B: Integer);
 begin
  WriteLn(A);
  WriteLn(B);
 end;

var
 l_RBP : NativeUInt;
 l_P : Pointer;
begin
 l_RBP := NativeUInt(GetRBP);
 l_S := 'XXX';
 Local1(10);
 Local2(10, 0);
 Call1(l3LocalStubPrim(GetRBP, @Local1));
 Call1(l3LocalStub(@Local1));
 Call2(l3LocalStubPrim(GetRBP, @Local2));
 Call2(l3LocalStub(@Local2));
 ReadLn;
end;

begin
  try
    Test;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.


Комментариев нет:

Отправить комментарий