mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-18 02:49:28 +02:00
* fixed basic signal handling for PowerPC64/linux, by updating related types and major code cleanup
git-svn-id: trunk@1364 -
This commit is contained in:
parent
0b34b01a6d
commit
3f4682400c
@ -19,43 +19,78 @@
|
|||||||
procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigContext);cdecl;
|
procedure SignalToRunerror(sig : longint; SigInfo: PSigInfo; SigContext: PSigContext);cdecl;
|
||||||
var
|
var
|
||||||
res : word;
|
res : word;
|
||||||
{ fpustate: longint; }
|
fpustate : qword;
|
||||||
|
{$IFDEF EXCDEBUG}
|
||||||
|
p : pbyte;
|
||||||
|
i, j : integer;
|
||||||
|
{$ENDIF}
|
||||||
begin
|
begin
|
||||||
res:=0;
|
res:=0;
|
||||||
{$IFDEF EXCDEBUG}
|
{$IFDEF EXCDEBUG}
|
||||||
writeln('signaltorunerror');
|
writeln('signaltorunerror');
|
||||||
|
{ dump SigContext }
|
||||||
|
p := pbyte(SigContext);
|
||||||
|
for j := 0 to sizeof(TSigContext) div 8 do begin
|
||||||
|
for i := 0 to 7 do begin
|
||||||
|
write(hexstr(p^, 2));
|
||||||
|
inc(p);
|
||||||
|
end;
|
||||||
|
write(' ');
|
||||||
|
end;
|
||||||
|
writeln;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
|
||||||
|
{ SigContext is actally a pointer to a ucontext structure.
|
||||||
|
So we do some ugly pointer casting to get it right again.
|
||||||
|
|
||||||
|
See also in the *kernel* sources arch/ppc64/kernel/signal.c,
|
||||||
|
function setup_rt_sigframe() }
|
||||||
|
|
||||||
|
SigContext := @(PUContext(SigContext)^.uc_mcontext);
|
||||||
|
|
||||||
{ exception flags are turned off by kernel }
|
{ exception flags are turned off by kernel }
|
||||||
fpc_enable_ppc_fpu_exceptions;
|
fpc_enable_ppc_fpu_exceptions;
|
||||||
case sig of
|
case sig of
|
||||||
SIGFPE :
|
SIGFPE :
|
||||||
begin
|
begin
|
||||||
{
|
{ ugly typecast to get the FPSCR register contents }
|
||||||
fpscr is cleared by the kernel -> can't find out cause :(
|
fpustate := QWord(PQWord(@SigContext^.fp_regs[PT_FPSCR])^);
|
||||||
fpustate := fpc_get_ppc_fpscr;
|
{$IFDEF EXCDEBUG}
|
||||||
if (fpustate and ppc_fpu_underflow) <> 0 then
|
writeln('fpustate = ', hexstr(fpustate, sizeof(fpustate)*2));
|
||||||
res := 206
|
{$ENDIF}
|
||||||
else if (fpustate and ppc_fpu_overflow) <> 0 then
|
|
||||||
res := 205
|
{ TODO: distinguishing FPU signal type does not work as it should
|
||||||
else if (fpustate and ppc_fpu_divbyzero) <> 0 then
|
if (fpustate and ppc_fpu_underflow) <> 0 then
|
||||||
res := 200
|
res := 206
|
||||||
else
|
else if (fpustate and ppc_fpu_overflow) <> 0 then
|
||||||
}
|
res := 205
|
||||||
res := 207;
|
else if (fpustate and ppc_fpu_divbyzero) <> 0 then
|
||||||
end;
|
res := 200
|
||||||
|
else }
|
||||||
|
res := 207;
|
||||||
|
end;
|
||||||
SIGBUS :
|
SIGBUS :
|
||||||
res:=214;
|
res:=214;
|
||||||
SIGILL,
|
SIGILL,
|
||||||
SIGSEGV :
|
SIGSEGV :
|
||||||
res:=216;
|
res:=216;
|
||||||
end;
|
end;
|
||||||
{$IFDEF EXCDEBUG}
|
{$IFDEF EXCDEBUG}
|
||||||
writeln('sig = ', sig);
|
writeln('sig = ', sig);
|
||||||
writeln('siginfo = ', hexstr(ptrint(siginfo), sizeof(siginfo)*2));
|
writeln('siginfo = ', hexstr(ptrint(siginfo), sizeof(siginfo)*2));
|
||||||
writeln('sigcontext = ', hexstr(ptrint(sigcontext), sizeof(sigcontext)*2));
|
writeln('sigcontext = ', hexstr(ptrint(sigcontext), sizeof(sigcontext)*2));
|
||||||
|
|
||||||
|
writeln('sigcontext...signal = ', hexstr(sigcontext^.signal, 16));
|
||||||
|
|
||||||
|
writeln('sigcontext^...regs = ', hexstr(ptrint(sigcontext^.regs), 16));
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
|
reenable_signal(sig);
|
||||||
{ give runtime error at the position where the signal was raised }
|
{ give runtime error at the position where the signal was raised }
|
||||||
|
|
||||||
if res<>0 then
|
if res<>0 then
|
||||||
HandleErrorAddrFrame(res,pointer(SigContext^.pt_regs^.nip),pointer(SigContext^.pt_regs^.gpr[1]));
|
HandleErrorAddrFrame(res, pointer(SigContext^.gp_regs[PT_NIP]), pointer(SigContext^.gp_regs[PT_R1]));
|
||||||
|
{$IFDEF EXCDEBUG}
|
||||||
|
readln;
|
||||||
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
{
|
{
|
||||||
This file is part of the Free Pascal run time library.
|
This file is part of the Free Pascal run time library.
|
||||||
Copyright (c) 1999-2000 by Jonas Maebe,
|
Copyright (c) 2005 by Thomas Schatzl
|
||||||
member of the Free Pascal development team.
|
|
||||||
|
|
||||||
TSigContext
|
TSigContext and associated structures
|
||||||
|
|
||||||
See the file COPYING.FPC, included in this distribution,
|
See the file COPYING.FPC, included in this distribution,
|
||||||
for details about the copyright.
|
for details about the copyright.
|
||||||
@ -17,65 +16,151 @@
|
|||||||
{$packrecords C}
|
{$packrecords C}
|
||||||
|
|
||||||
type
|
type
|
||||||
TPPC_Reg = QWord;
|
gpr_reg = cULong;
|
||||||
|
fpr_reg = double;
|
||||||
|
vvr_reg = array[0..1] of cULong;
|
||||||
|
|
||||||
|
type
|
||||||
{ from include/asm-ppc64/ptrace.h }
|
{ from include/asm-ppc64/ptrace.h }
|
||||||
pptregs = ^tptregs;
|
ppt_regs = ^pt_regs;
|
||||||
tptregs = record
|
pt_regs = record
|
||||||
gpr: array[0..31] of TPPC_Reg;
|
gpr : array[0..31] of gpr_reg;
|
||||||
nip: TPPC_Reg;
|
nip : gpr_reg;
|
||||||
msr: TPPC_Reg;
|
msr : gpr_reg;
|
||||||
orig_gpr3: TPPC_Reg; { Used for restarting system calls }
|
orig_gpr3 : gpr_reg; { Used for restarting system calls }
|
||||||
ctr: TPPC_Reg;
|
ctr : gpr_reg;
|
||||||
link: TPPC_Reg;
|
link : gpr_reg;
|
||||||
xer: TPPC_Reg;
|
xer : gpr_reg;
|
||||||
ccr: TPPC_Reg;
|
ccr : gpr_reg;
|
||||||
softe: TPPC_Reg; { soft enabled/disabled }
|
softe : gpr_reg; { Soft enabled/disabled }
|
||||||
trap: TPPC_Reg; { Reason for being here }
|
trap : gpr_reg; { Reason for being here }
|
||||||
dar: TPPC_Reg; { Fault registers }
|
dar : gpr_reg; { Fault registers }
|
||||||
dsisr: TPPC_Reg;
|
dsisr : gpr_reg;
|
||||||
result: TPPC_Reg; { Result of a system call }
|
result : gpr_reg; { Result of a system call }
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ index constants for the different register set arrays in TSigContext.
|
||||||
|
Comments were directly pasted from the sources.
|
||||||
|
}
|
||||||
|
const
|
||||||
|
PT_R0 = 0;
|
||||||
|
PT_R1 = 1;
|
||||||
|
PT_R2 = 2;
|
||||||
|
PT_R3 = 3;
|
||||||
|
PT_R4 = 4;
|
||||||
|
PT_R5 = 5;
|
||||||
|
PT_R6 = 6;
|
||||||
|
PT_R7 = 7;
|
||||||
|
PT_R8 = 8;
|
||||||
|
PT_R9 = 9;
|
||||||
|
PT_R10 = 10;
|
||||||
|
PT_R11 = 11;
|
||||||
|
PT_R12 = 12;
|
||||||
|
PT_R13 = 13;
|
||||||
|
PT_R14 = 14;
|
||||||
|
PT_R15 = 15;
|
||||||
|
PT_R16 = 16;
|
||||||
|
PT_R17 = 17;
|
||||||
|
PT_R18 = 18;
|
||||||
|
PT_R19 = 19;
|
||||||
|
PT_R20 = 20;
|
||||||
|
PT_R21 = 21;
|
||||||
|
PT_R22 = 22;
|
||||||
|
PT_R23 = 23;
|
||||||
|
PT_R24 = 24;
|
||||||
|
PT_R25 = 25;
|
||||||
|
PT_R26 = 26;
|
||||||
|
PT_R27 = 27;
|
||||||
|
PT_R28 = 28;
|
||||||
|
PT_R29 = 29;
|
||||||
|
PT_R30 = 30;
|
||||||
|
PT_R31 = 31;
|
||||||
|
PT_NIP = 32;
|
||||||
|
PT_MSR = 33;
|
||||||
|
PT_CTR = 35;
|
||||||
|
PT_LNK = 36;
|
||||||
|
PT_XER = 37;
|
||||||
|
PT_CCR = 38;
|
||||||
|
PT_SOFTE = 39;
|
||||||
|
PT_RESULT = 43;
|
||||||
|
PT_FPR0 = 48;
|
||||||
|
PT_FPR31 = PT_FPR0+31;
|
||||||
|
{ Kernel and userspace will both use this PT_FPSCR value. 32-bit apps will have
|
||||||
|
visibility to the asm-ppc/ptrace.h header instead of this one. }
|
||||||
|
{ each FP reg occupies 1 slot in 64-bit space }
|
||||||
|
PT_FPSCR = PT_FPR0+32;
|
||||||
|
{ each Vector reg occupies 2 slots in 64-bit }
|
||||||
|
PT_VR0 = 82;
|
||||||
|
PT_VSCR = (PT_VR0+(32*2))+1;
|
||||||
|
PT_VRSAVE = PT_VR0+(33*2);
|
||||||
|
|
||||||
{ from include/asm-ppc64/signal.h }
|
{ from include/asm-ppc64/signal.h }
|
||||||
|
type
|
||||||
stack_t = record
|
stack_t = record
|
||||||
ss_sp: pointer;
|
ss_sp : pointer;
|
||||||
ss_flags: longint;
|
ss_flags : cInt;
|
||||||
ss_size: size_t;
|
ss_size : size_t;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ from include/asm-ppc64/sigcontext.h }
|
{ from include/asm-ppc64/sigcontext.h and
|
||||||
tsigcontext_struct = record
|
include/asm-ppc64/elf.h
|
||||||
_unused: array[0..3] of qword;
|
}
|
||||||
signal: longint;
|
const
|
||||||
pad0 : longint;
|
ELF_NGREG = 48; { includes nip, msr, lr, etc. }
|
||||||
handler: qword;
|
ELF_NFPREG = 33; { includes fpscr }
|
||||||
oldmask: qword;
|
ELF_NVRREG = 34; { includes vscr & vrsave in split vectors }
|
||||||
pt_regs: pptregs;
|
|
||||||
|
type
|
||||||
|
elf_gregset_t = array[0..ELF_NGREG-1] of gpr_reg;
|
||||||
|
elf_fpregset_t = array[0..ELF_NFPREG-1] of fpr_reg;
|
||||||
|
|
||||||
|
elf_vrreg_t = array[0..ELF_NVRREG-1] of vvr_reg;
|
||||||
|
|
||||||
|
TSigContext = record
|
||||||
|
_unused : array[0..3] of cULong;
|
||||||
|
signal : cInt;
|
||||||
|
_pad0 : cInt;
|
||||||
|
handler : cULong;
|
||||||
|
oldmask : cULong;
|
||||||
|
regs : ppt_regs;
|
||||||
|
gp_regs : elf_gregset_t;
|
||||||
|
fp_regs : elf_fpregset_t;
|
||||||
|
|
||||||
|
{ To maintain compatibility with current implementations the sigcontext is
|
||||||
|
extended by appending a pointer (v_regs) to a quadword type (elf_vrreg_t)
|
||||||
|
followed by an unstructured (vmx_reserve) field of 69 doublewords. This
|
||||||
|
allows the array of vector registers to be quadword aligned independent of
|
||||||
|
the alignment of the containing sigcontext or ucontext. It is the
|
||||||
|
responsibility of the code setting the sigcontext to set this pointer to
|
||||||
|
either NULL (if this processor does not support the VMX feature) or the
|
||||||
|
address of the first quadword within the allocated (vmx_reserve) area.
|
||||||
|
|
||||||
|
The pointer (v_regs) of vector type (elf_vrreg_t) is type compatible with
|
||||||
|
an array of 34 quadword entries (elf_vrregset_t). The entries with
|
||||||
|
indexes 0-31 contain the corresponding vector registers. The entry with
|
||||||
|
index 32 contains the vscr as the last word (offset 12) within the
|
||||||
|
quadword. This allows the vscr to be stored as either a quadword (since
|
||||||
|
it must be copied via a vector register to/from storage) or as a word.
|
||||||
|
The entry with index 33 contains the vrsave as the first word (offset 0)
|
||||||
|
within the quadword. }
|
||||||
|
v_regs : ^elf_vrreg_t;
|
||||||
|
vmx_reserve : array[0..ELF_NVRREG+ELF_NVRREG] of cLong;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ the kernel uses a different sigset_t type for the ucontext structure and the
|
||||||
|
sigset_t used for masking signals. To avoid name clash, and still use a dedicated
|
||||||
|
type for the fields, use _sigset_t }
|
||||||
|
_sigset_t = cULong;
|
||||||
|
|
||||||
{ from include/asm-ppc64/ucontext.h }
|
{ from include/asm-ppc64/ucontext.h }
|
||||||
pucontext = ^tucontext;
|
pucontext = ^tucontext;
|
||||||
tucontext = record
|
tucontext = record
|
||||||
uc_flags : qword;
|
uc_flags : cuLong;
|
||||||
uc_link : pucontext;
|
uc_link : pucontext;
|
||||||
uc_stack : stack_t;
|
uc_stack : stack_t;
|
||||||
uc_sigmask : qword;{sigset_t;}
|
uc_sigmask : _sigset_t;
|
||||||
__unused : array[0..14] of qword;{sigset_t;}
|
__unused : array[0..14] of _sigset_t; { Allow for uc_sigmask growth }
|
||||||
uc_mcontext : tsigcontext_struct;
|
uc_mcontext : TSigContext; { last for extensibility }
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
{ from arch/ppc/kernel/signal.c, the type of the actual parameter passed }
|
|
||||||
{ to the sigaction handler }
|
|
||||||
t_rt_sigframe = record
|
|
||||||
uc: tucontext;
|
|
||||||
_unused: array[0..1] of qword;
|
|
||||||
tramp: array[0..5] of dword;
|
|
||||||
pinfo: psiginfo;
|
|
||||||
puc: pointer;
|
|
||||||
siginfo: tsiginfo;
|
|
||||||
abigap: array[0..287] of byte;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
PSigContext = ^TSigContext;
|
PSigContext = ^TSigContext;
|
||||||
TSigContext= tsigcontext_struct;
|
|
||||||
|
@ -21,14 +21,14 @@
|
|||||||
{****************************************************************************
|
{****************************************************************************
|
||||||
PowerPC specific stuff
|
PowerPC specific stuff
|
||||||
****************************************************************************}
|
****************************************************************************}
|
||||||
{
|
|
||||||
const
|
const
|
||||||
ppc_fpu_overflow = (1 shl (32-3));
|
ppc_fpu_overflow = (1 shl (32-3));
|
||||||
ppc_fpu_underflow = (1 shl (32-4));
|
ppc_fpu_underflow = (1 shl (32-4));
|
||||||
ppc_fpu_divbyzero = (1 shl (32-5));
|
ppc_fpu_divbyzero = (1 shl (32-5));
|
||||||
ppc_fpu_inexact = (1 shl (32-6));
|
ppc_fpu_inexact = (1 shl (32-6));
|
||||||
ppc_fpu_invalid_snan = (1 shl (32-7));
|
ppc_fpu_invalid_snan = (1 shl (32-7));
|
||||||
}
|
|
||||||
|
|
||||||
procedure fpc_enable_ppc_fpu_exceptions;
|
procedure fpc_enable_ppc_fpu_exceptions;
|
||||||
assembler; nostackframe;
|
assembler; nostackframe;
|
||||||
@ -67,12 +67,12 @@ asm
|
|||||||
stfd f0,temp
|
stfd f0,temp
|
||||||
lwz r3,temp.b
|
lwz r3,temp.b
|
||||||
{ clear all exception flags }
|
{ clear all exception flags }
|
||||||
{
|
{ TODO
|
||||||
rlwinm r4,r3,0,16,31
|
rlwinm r4,r3,0,16,31
|
||||||
stw r4,temp.b
|
stw r4,temp.b
|
||||||
lfd f0,temp
|
lfd f0,temp
|
||||||
a_mtfsf f0
|
mtfsf f0
|
||||||
}
|
}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -930,20 +930,16 @@ asm
|
|||||||
mr r3, r1
|
mr r3, r1
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{NOTE: On MACOS, 68000 code might call powerpc code, through the MixedMode manager,
|
|
||||||
(even in the OS in system 9). The pointer to the switching stack frame is
|
|
||||||
indicated by the first bit set to 1. This is checked below.}
|
|
||||||
|
|
||||||
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
|
{$define FPC_SYSTEM_HAS_GET_CALLER_ADDR}
|
||||||
function get_caller_addr(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe;
|
function get_caller_addr(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe;
|
||||||
asm
|
asm
|
||||||
cmpldi r3,0
|
cmpldi r3,0
|
||||||
beq .Lcaller_addr_frame_null
|
beq .Lcaller_addr_frame_null
|
||||||
ld r3,0(r3)
|
ld r3, 0(r3)
|
||||||
|
|
||||||
cmpldi r3,0
|
cmpldi r3,0
|
||||||
beq .Lcaller_addr_frame_null
|
beq .Lcaller_addr_frame_null
|
||||||
ld r3,16(r3)
|
ld r3, 16(r3)
|
||||||
.Lcaller_addr_frame_null:
|
.Lcaller_addr_frame_null:
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -953,7 +949,7 @@ function get_caller_frame(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLIN
|
|||||||
asm
|
asm
|
||||||
cmpldi r3,0
|
cmpldi r3,0
|
||||||
beq .Lcaller_frame_null
|
beq .Lcaller_frame_null
|
||||||
ld r3,0(r3)
|
ld r3, 0(r3)
|
||||||
.Lcaller_frame_null:
|
.Lcaller_frame_null:
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user