* 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:
tom_at_work 2005-10-12 22:46:13 +00:00
parent 0b34b01a6d
commit 3f4682400c
3 changed files with 194 additions and 78 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;