mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-08 09:28:19 +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;
|
||||
var
|
||||
res : word;
|
||||
{ fpustate: longint; }
|
||||
fpustate : qword;
|
||||
{$IFDEF EXCDEBUG}
|
||||
p : pbyte;
|
||||
i, j : integer;
|
||||
{$ENDIF}
|
||||
begin
|
||||
res:=0;
|
||||
{$IFDEF EXCDEBUG}
|
||||
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}
|
||||
|
||||
{ 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 }
|
||||
fpc_enable_ppc_fpu_exceptions;
|
||||
case sig of
|
||||
SIGFPE :
|
||||
begin
|
||||
{
|
||||
fpscr is cleared by the kernel -> can't find out cause :(
|
||||
fpustate := fpc_get_ppc_fpscr;
|
||||
if (fpustate and ppc_fpu_underflow) <> 0 then
|
||||
res := 206
|
||||
else if (fpustate and ppc_fpu_overflow) <> 0 then
|
||||
res := 205
|
||||
else if (fpustate and ppc_fpu_divbyzero) <> 0 then
|
||||
res := 200
|
||||
else
|
||||
}
|
||||
res := 207;
|
||||
end;
|
||||
begin
|
||||
{ ugly typecast to get the FPSCR register contents }
|
||||
fpustate := QWord(PQWord(@SigContext^.fp_regs[PT_FPSCR])^);
|
||||
{$IFDEF EXCDEBUG}
|
||||
writeln('fpustate = ', hexstr(fpustate, sizeof(fpustate)*2));
|
||||
{$ENDIF}
|
||||
|
||||
{ TODO: distinguishing FPU signal type does not work as it should
|
||||
if (fpustate and ppc_fpu_underflow) <> 0 then
|
||||
res := 206
|
||||
else if (fpustate and ppc_fpu_overflow) <> 0 then
|
||||
res := 205
|
||||
else if (fpustate and ppc_fpu_divbyzero) <> 0 then
|
||||
res := 200
|
||||
else }
|
||||
res := 207;
|
||||
end;
|
||||
SIGBUS :
|
||||
res:=214;
|
||||
res:=214;
|
||||
SIGILL,
|
||||
SIGSEGV :
|
||||
res:=216;
|
||||
res:=216;
|
||||
end;
|
||||
{$IFDEF EXCDEBUG}
|
||||
writeln('sig = ', sig);
|
||||
writeln('siginfo = ', hexstr(ptrint(siginfo), sizeof(siginfo)*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}
|
||||
reenable_signal(sig);
|
||||
{ give runtime error at the position where the signal was raised }
|
||||
|
||||
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;
|
||||
|
||||
|
@ -1,9 +1,8 @@
|
||||
{
|
||||
This file is part of the Free Pascal run time library.
|
||||
Copyright (c) 1999-2000 by Jonas Maebe,
|
||||
member of the Free Pascal development team.
|
||||
Copyright (c) 2005 by Thomas Schatzl
|
||||
|
||||
TSigContext
|
||||
TSigContext and associated structures
|
||||
|
||||
See the file COPYING.FPC, included in this distribution,
|
||||
for details about the copyright.
|
||||
@ -17,65 +16,151 @@
|
||||
{$packrecords C}
|
||||
|
||||
type
|
||||
TPPC_Reg = QWord;
|
||||
gpr_reg = cULong;
|
||||
fpr_reg = double;
|
||||
vvr_reg = array[0..1] of cULong;
|
||||
|
||||
type
|
||||
{ from include/asm-ppc64/ptrace.h }
|
||||
pptregs = ^tptregs;
|
||||
tptregs = record
|
||||
gpr: array[0..31] of TPPC_Reg;
|
||||
nip: TPPC_Reg;
|
||||
msr: TPPC_Reg;
|
||||
orig_gpr3: TPPC_Reg; { Used for restarting system calls }
|
||||
ctr: TPPC_Reg;
|
||||
link: TPPC_Reg;
|
||||
xer: TPPC_Reg;
|
||||
ccr: TPPC_Reg;
|
||||
softe: TPPC_Reg; { soft enabled/disabled }
|
||||
trap: TPPC_Reg; { Reason for being here }
|
||||
dar: TPPC_Reg; { Fault registers }
|
||||
dsisr: TPPC_Reg;
|
||||
result: TPPC_Reg; { Result of a system call }
|
||||
ppt_regs = ^pt_regs;
|
||||
pt_regs = record
|
||||
gpr : array[0..31] of gpr_reg;
|
||||
nip : gpr_reg;
|
||||
msr : gpr_reg;
|
||||
orig_gpr3 : gpr_reg; { Used for restarting system calls }
|
||||
ctr : gpr_reg;
|
||||
link : gpr_reg;
|
||||
xer : gpr_reg;
|
||||
ccr : gpr_reg;
|
||||
softe : gpr_reg; { Soft enabled/disabled }
|
||||
trap : gpr_reg; { Reason for being here }
|
||||
dar : gpr_reg; { Fault registers }
|
||||
dsisr : gpr_reg;
|
||||
result : gpr_reg; { Result of a system call }
|
||||
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 }
|
||||
type
|
||||
stack_t = record
|
||||
ss_sp: pointer;
|
||||
ss_flags: longint;
|
||||
ss_size: size_t;
|
||||
ss_sp : pointer;
|
||||
ss_flags : cInt;
|
||||
ss_size : size_t;
|
||||
end;
|
||||
|
||||
{ from include/asm-ppc64/sigcontext.h }
|
||||
tsigcontext_struct = record
|
||||
_unused: array[0..3] of qword;
|
||||
signal: longint;
|
||||
pad0 : longint;
|
||||
handler: qword;
|
||||
oldmask: qword;
|
||||
pt_regs: pptregs;
|
||||
{ from include/asm-ppc64/sigcontext.h and
|
||||
include/asm-ppc64/elf.h
|
||||
}
|
||||
const
|
||||
ELF_NGREG = 48; { includes nip, msr, lr, etc. }
|
||||
ELF_NFPREG = 33; { includes fpscr }
|
||||
ELF_NVRREG = 34; { includes vscr & vrsave in split vectors }
|
||||
|
||||
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;
|
||||
|
||||
{ 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 }
|
||||
pucontext = ^tucontext;
|
||||
tucontext = record
|
||||
uc_flags : qword;
|
||||
uc_flags : cuLong;
|
||||
uc_link : pucontext;
|
||||
uc_stack : stack_t;
|
||||
uc_sigmask : qword;{sigset_t;}
|
||||
__unused : array[0..14] of qword;{sigset_t;}
|
||||
uc_mcontext : tsigcontext_struct;
|
||||
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;
|
||||
uc_sigmask : _sigset_t;
|
||||
__unused : array[0..14] of _sigset_t; { Allow for uc_sigmask growth }
|
||||
uc_mcontext : TSigContext; { last for extensibility }
|
||||
end;
|
||||
|
||||
PSigContext = ^TSigContext;
|
||||
TSigContext= tsigcontext_struct;
|
||||
|
@ -21,14 +21,14 @@
|
||||
{****************************************************************************
|
||||
PowerPC specific stuff
|
||||
****************************************************************************}
|
||||
{
|
||||
|
||||
const
|
||||
ppc_fpu_overflow = (1 shl (32-3));
|
||||
ppc_fpu_underflow = (1 shl (32-4));
|
||||
ppc_fpu_divbyzero = (1 shl (32-5));
|
||||
ppc_fpu_inexact = (1 shl (32-6));
|
||||
ppc_fpu_invalid_snan = (1 shl (32-7));
|
||||
}
|
||||
|
||||
|
||||
procedure fpc_enable_ppc_fpu_exceptions;
|
||||
assembler; nostackframe;
|
||||
@ -67,12 +67,12 @@ asm
|
||||
stfd f0,temp
|
||||
lwz r3,temp.b
|
||||
{ clear all exception flags }
|
||||
{
|
||||
{ TODO
|
||||
rlwinm r4,r3,0,16,31
|
||||
stw r4,temp.b
|
||||
lfd f0,temp
|
||||
a_mtfsf f0
|
||||
}
|
||||
mtfsf f0
|
||||
}
|
||||
end;
|
||||
|
||||
|
||||
@ -930,20 +930,16 @@ asm
|
||||
mr r3, r1
|
||||
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}
|
||||
function get_caller_addr(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLINE}inline;{$endif} nostackframe;
|
||||
asm
|
||||
cmpldi r3,0
|
||||
beq .Lcaller_addr_frame_null
|
||||
ld r3,0(r3)
|
||||
ld r3, 0(r3)
|
||||
|
||||
cmpldi r3,0
|
||||
beq .Lcaller_addr_frame_null
|
||||
ld r3,16(r3)
|
||||
ld r3, 16(r3)
|
||||
.Lcaller_addr_frame_null:
|
||||
end;
|
||||
|
||||
@ -953,7 +949,7 @@ function get_caller_frame(framebp:pointer):pointer;assembler;{$ifdef SYSTEMINLIN
|
||||
asm
|
||||
cmpldi r3,0
|
||||
beq .Lcaller_frame_null
|
||||
ld r3,0(r3)
|
||||
ld r3, 0(r3)
|
||||
.Lcaller_frame_null:
|
||||
end;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user