[fpc-pascal] Re: assign code to a method

2011-02-24 Thread Angel Montesinos



The correct statement is therefore:

Move(functionCode[1], FBlock^.code^, len);

It would also be cleaner to use a dynamic array instead of a string
to store arbitrary binary data (in that case, you'd have to use
functionCode[0] above though).


I have tried yours and other combinations. The following one works at 
last in Delphi6 PE. This will keep me occupied some time updating my 
32 bits programs, so that they will be DEP safe. Thanks to you all. 
Note that I have dropped the use of Move. As for fpc-Lazarus 64 bits, 
it does not work yet: more about this in another thread.



{--code snippet begins--}

  len:= Length(cod);   { cod  is the ansiString containing
 the opcodes to be executed}
  SetLength(ba, len);   { ba   is an auxiliary array of bytes}
  for i:= 0 to len-1 do
ba[i]:= ord(cod[i+1]);

  { exeBlock   has been declared as PChar }
  exeBlock:= VirtualAlloc(nil, len + SizeOf(exeBlock), MEM_COMMIT,
  PAGE_EXECUTE_READWRITE);
  for i:= 0 to len-1 do
exeBlock[i]:= chr(ba[i]);

  @F:= @exeBlock[0];  {  F  is the function whose code is
   here assigned to  cod}

  ba:= nil;
  cod:= '';

{--code ended---}

For people interested in details: the use of an AnsiString for storing 
the opcodes, that is for building cod, eases this by the use of the 
special procedures to treat strings (adding them, etc.).
The use of exeBlock as PChar serves to guarantee that a contiguous 
chunk of memory starting in exeBlock[0] becomes reserved for the 
exclusive use of exeBlock and cannot overlap another variable: this is 
my interpretation of the failure that did happen when, after assigning 
the code to F, I did put  cod = ''.



--
montesin at uv dot es

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


[fpc-pascal] Re: assign code to a method

2011-02-22 Thread Angel Montesinos



Many thanks, Andrew. I intend to apply this to my old programs in 32
bit Windows. I'll tell you about the outcome.


Below you will see a console application for testing your suggestions 
or better my understanding of them. The results are (in Windows XP 64 
bits Pro):


   1. When Data Execution Prevention (DEP) is enforced, the program 
fails.


   2. When DEP is enforced only for essential Windows programs, the 
program functions (that is, it writes the value of pi). But if

one uncomments the commented line of code, that is  makes
   codeFunction:= '',
the program fails.


What may be happening here?

Many thanks






--
montesin at uv dot es


{--begins code for console app--}

program Test_VirtualAlloc;

{$APPTYPE CONSOLE}

uses
  SysUtils, Types, Windows;

type

  PCodeBlock= ^CodeBlock;
  CodeBlock = record
size: DWord;
code: Pointer;
  end;

  RealFunction = function(const X : array of Extended) : Extended;

  TOpCodeFunctionExtended = class(TObject)
  private
functionCode : AnsiString; {the function opCode sequence}
  public
F : function(const X : array of Extended) : Extended;
FBlock: PCodeBlock;
constructor Create;
destructor Destroy; override;
  end;

  var
theF: TOpCodeFunctionExtended;
rslt: Extended;
linetxt: AnsiString;


  constructor TOpCodeFunctionExtended.Create;
  var
len: Integer;
  begin
inherited;

{execution of this puts pi in the register st(0) of FPU}
functionCode:= #$55  +   {push ebp}
   #$8B#$EC +{mov ebp, esp}
   #$D9#$EB +{fldpi}
   #$C9 +{leave}
   #$C3; {ret}

len:= Length(functionCode);

FBlock:= VirtualAlloc(nil, len + SizeOf(codeBlock), MEM_COMMIT, 
PAGE_EXECUTE_READWRITE);

Move(functionCode, PChar(FBlock^.code), len);
FBlock.size:= len;

@F := FBlock^.code;   {assignation of code to the function}

//functionCode:= '';  {if this is uncommented, program fails}
  end;

  destructor TOpCodeFunctionExtended.Destroy;
  begin
if FBlock  nil then begin
  VirtualFree(FBlock, 0, MEM_RELEASE);
  FBlock:= nil;
end;
theF.Free;
inherited
  end;


begin
  theF:= TOpCodeFunctionExtended.Create;
  Writeln('Enter a character. For exiting, enter an ''x''');
  Writeln;
  try
repeat
  readln(linetxt);
  if linetxt  'x'  then begin
rslt:= theF.F([]);
writeln(FloatToStrF(rslt, ffFixed, 18, 18));
  end;
until linetxt = 'x';
  except on exception do
;
  end;
end.

{--ends code for console app--}

___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: assign code to a method

2011-02-22 Thread Jonas Maebe

On 22 Feb 2011, at 21:24, Angel Montesinos wrote:

 one uncomments the commented line of code, that is  makes
   codeFunction:= '',
 the program fails.
 
 
 What may be happening here?

This code is wrong:

   functionCode : AnsiString; {the function opCode sequence}
...
   Move(functionCode, PChar(FBlock^.code), len);

An ansistring is a pointer. Move takes formal const/var parameters. So the 
move() moves the pointer along with whatever data comes after it over the 
FBlock^.code pointer and whatever data comes after that. What you want, is to 
move the data to which functionCode points into the memory block to which 
FBlock^.code points. The correct statement is therefore:

   Move(functionCode[1], FBlock^.code^, len);

It would also be cleaner to use a dynamic array instead of a string to store 
arbitrary binary data (in that case, you'd have to use functionCode[0] above 
though).


Jonas___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


Re: [fpc-pascal] Re: assign code to a method

2011-02-22 Thread Paul Nicholls
I second the motion of using a Dynamic array too instead of the manual 
creation/destruction of a memory block.


I use this for a virtual machine I created a few years back and it works 
under XP/Vista for me :)


cheers,
Paul

- Original Message - 
From: Jonas Maebe jonas.ma...@elis.ugent.be

To: FPC-Pascal users discussions fpc-pascal@lists.freepascal.org
Sent: Wednesday, February 23, 2011 7:54 AM
Subject: Re: [fpc-pascal] Re: assign code to a method



On 22 Feb 2011, at 21:24, Angel Montesinos wrote:


one uncomments the commented line of code, that is  makes
  codeFunction:= '',
the program fails.


What may be happening here?


This code is wrong:

  functionCode : AnsiString; {the function opCode sequence}
...
  Move(functionCode, PChar(FBlock^.code), len);

An ansistring is a pointer. Move takes formal const/var parameters. So the 
move() moves the pointer along with whatever data comes after it over the 
FBlock^.code pointer and whatever data comes after that. What you want, is 
to move the data to which functionCode points into the memory block to which 
FBlock^.code points. The correct statement is therefore:


  Move(functionCode[1], FBlock^.code^, len);

It would also be cleaner to use a dynamic array instead of a string to store 
arbitrary binary data (in that case, you'd have to use functionCode[0] above 
though).



Jonas___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal 


___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


[fpc-pascal] Re: assign code to a method

2011-02-19 Thread Angel Montesinos

El 18/02/2011 13:46, Sven Barth escribió:


I personally would say that mapping a page with the Execute flag set
and storing the to-be-executed content there should be enough. After
all JIT compilers must do that as well. ;)


Thanks. I shall study this issue.


--
montesin at uv dot es


___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal


[fpc-pascal] Re: assign code to a method

2011-02-19 Thread Angel Montesinos

El 18/02/2011 17:59, Andrew Haines escribió:


From the other comments it seems like you are writing some assembly to

memory at runtime then calling that code?


That is right.


If so then maybe the following
can help you.



...code...



so the usage would be like so



function TTrampolineManager.GenerateCode(args: ): Pointer;
begin
try
   Result := CurrentBlock.Position; // = @Block + Block.Cursor
   repeat
 WriteData(your_data, size_of_data);
   until done;

except
 on e: TrampolineBlockFullException do
   begin
 TrampolineManager.AllocateBlock;
 Result := GenerateCode(args);
   end;
   end;
end;


Hope this helps :)


A lot! I understand that for purposes other than trampolining, the 
essence of this is the the way of building an almost contiguous list, say


 Block: array[0..lastCodePiece] of Pointer;

of DEP executable codes inside an authorized chunk of memory, and that 
the call for assigning one of them, Block[i], to some function declared as


otherObject.thisFunction(other args): Double;

would be

  @otherObjectInstance.thisFunction:= Block[i];

And also the way to obtain another block when one of them has
been exhausted, and the way of disposing of them, right?

Many thanks, Andrew. I intend to apply this to my old programs in 32 
bit Windows. I'll tell you about the outcome.




--
montesin at uv dot es


___
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
http://lists.freepascal.org/mailman/listinfo/fpc-pascal