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

View File

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

View File

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