-
-
Notifications
You must be signed in to change notification settings - Fork 325
Open
Description
Hi,
using the last version of P4D on RPI 5 leads to Exception External SIGSEGV.
Problem is in method function GetCallBack(Self: TObject; Method: Pointer; ArgNum: Integer;
CallType: TCallType): Pointer;
nmap didn't allocate the memory.
I have solved this problem changing the method code in way
{$IFDEF CPUARM64}
function GetCallBack(Self: TObject; Method: Pointer; ArgNum: Integer;
CallType: TCallType): Pointer;
const
S1: array[0..79] of byte = (
//big-endian
//offset <_start>:
$fd, $7b, $bf, $a9, // stp x29, x30, [sp, #-16]!
$fd, $03, $00, $91, // mov x29, sp
$e0, $07, $bf, $a9, // stp x0, x1, [sp, #-16]!
$e2, $0f, $bf, $a9, // stp x2, x3, [sp, #-16]!
$e4, $17, $bf, $a9, // stp x4, x5, [sp, #-16]!
$e6, $1f, $bf, $a9, // stp x6, x7, [sp, #-16]!
$0a, $00, $00, $10, // adr x10, #0 <_start+0x18>
$40, $15, $40, $f9, // ldr x0, [x10, #40]
$49, $19, $40, $f9, // ldr x9, [x10, #48]
$e7, $2f, $c1, $a8, // ldp x7, x11, [sp], #16
$e5, $1b, $c1, $a8, // ldp x5, x6, [sp], #16
$e3, $13, $c1, $a8, // ldp x3, x4, [sp], #16
$e1, $0b, $c1, $a8, // ldp x1, x2, [sp], #16
$20, $01, $3f, $d6, // blr x9
$fd, $7b, $c1, $a8, // ldp x29, x30, [sp], #16
$c0, $03, $5f, $d6, // ret
$00, $00, $00, $00, // .word 0x00000000 //Self
$00, $00, $00, $00, // .word 0x00000000
$00, $00, $00, $00, // .word 0x00000000 //Method
$00, $00, $00, $00 // .word 0x00000000
);
const
PageSize = 4096;
var
P, Q: PByte;
LLiteralPool: TArray<pointer>;
I: Integer;
addr: Pointer;
begin
GetCodeMem(Q, SizeOf(S1));
if Q = nil then
begin
addr := fpMmap(nil, PageSize, PROT_READ or PROT_WRITE or PROT_EXEC, MAP_PRIVATE or MAP_ANONYMOUS, -1, 0);
if addr = Pointer(-1) then
{$IFDEF UNIX}
raise Exception.Create('mmap failed: ' + SysErrorMessage(GetLastOSError));
{$ENDIF}
Q := PByte(addr);
end;
P := Q;
Move(S1, P^, SizeOf(S1));
LLiteralPool := TArray<pointer>.Create(Self, Method);
Inc(P, Length(S1) - (Length(LLiteralPool) * SizeOf(pointer)));
for I := Low(LLiteralPool) to High(LLiteralPool) do begin
Move(LLiteralPool[I], P^, SizeOf(pointer));
Inc(P, SizeOf(pointer));
end;
{$IFDEF UNIX}
if fpMprotect(Pointer(Q), SizeOf(S1), PROT_READ or PROT_EXEC) <> 0 then
raise Exception.Create('mprotect failed: ' + SysErrorMessage(GetLastOSError));
{$ENDIF}
{$IF DEFINED(OSX) AND DEFINED(CPUARM64)}
{
macOS for M1 has a bug (Apple Feedback FB8994773) in which mprotect
rejects a permission change from NONE -> RWX.
Solution: give RW permission, make memory changes, then change RW to X
}
//X permission to the entire page for executions...
if mprotect(CodeMemPages, PageSize, PROT_EXEC) <> 0 then
raise EMProtectError.CreateFmt('MProtect error: %s', [
SysErrorMessage({$IFDEF FPC}GetLastOSError{$ELSE}GetLastError{$ENDIF}())]);
{$IFEND}
Result := Pointer(Q); //set arm mode
end;
{$ENDIF CPUARM64} Maybe that will help to someone.
Best regards
Bojan
Metadata
Metadata
Assignees
Labels
No labels