浏览代码

* x86_64 exception handling fixed

florian 21 年之前
父节点
当前提交
ee4b23ccac
共有 5 个文件被更改,包括 148 次插入50 次删除
  1. 9 4
      rtl/linux/osmain.inc
  2. 32 9
      rtl/linux/ossysc.inc
  3. 50 3
      rtl/linux/signal.inc
  4. 46 33
      rtl/linux/x86_64/sighnd.inc
  5. 11 1
      rtl/x86_64/x86_64.inc

+ 9 - 4
rtl/linux/osmain.inc

@@ -507,8 +507,6 @@ var
   act: SigActionRec;
   act: SigActionRec;
 
 
 Procedure InstallSignals;
 Procedure InstallSignals;
-var
-  oldact: SigActionRec;
 begin
 begin
   { Initialize the sigaction structure }
   { Initialize the sigaction structure }
   { all flags and information set to zero }
   { all flags and information set to zero }
@@ -516,7 +514,11 @@ begin
   { initialize handler                    }
   { initialize handler                    }
   act.sa_handler := signalhandler(@SignalToRunError);
   act.sa_handler := signalhandler(@SignalToRunError);
 {$ifdef RTSIGACTION}
 {$ifdef RTSIGACTION}
-  act.sa_flags:=4;
+  act.sa_flags:=4
+{$ifdef x86_64}
+    or $4000000
+{$endif x86_64}
+    ;
 {$endif RTSIGACTION}
 {$endif RTSIGACTION}
   FpSigAction(SIGFPE,@act,nil);
   FpSigAction(SIGFPE,@act,nil);
   FpSigAction(SIGSEGV,@act,nil);
   FpSigAction(SIGSEGV,@act,nil);
@@ -584,7 +586,10 @@ end;
 
 
 {
 {
  $Log$
  $Log$
- Revision 1.16  2004-04-27 20:47:00  florian
+ Revision 1.17  2004-05-01 15:59:17  florian
+   * x86_64 exception handling fixed
+
+ Revision 1.16  2004/04/27 20:47:00  florian
    * tried to fix x86-64 signal handling
    * tried to fix x86-64 signal handling
 
 
  Revision 1.15  2004/04/22 21:16:35  peter
  Revision 1.15  2004/04/22 21:16:35  peter

+ 32 - 9
rtl/linux/ossysc.inc

@@ -15,6 +15,13 @@
 
 
  ****************************************************************************
  ****************************************************************************
 }
 }
+{$ifdef CPUARM}
+{$define RTSIGACTION}
+{$endif CPUARM}
+
+{$ifdef CPUx86_64}
+{$define RTSIGACTION}
+{$endif CPUx86_64}
 
 
 {$I syscallh.inc}
 {$I syscallh.inc}
 {$I ostypes.inc}
 {$I ostypes.inc}
@@ -206,14 +213,6 @@ end;
   If OldAct is non-nil the previous action is saved there.
   If OldAct is non-nil the previous action is saved there.
 }
 }
 
 
-{$ifdef CPUARM}
-{$define RTSIGACTION}
-{$endif CPUARM}
-
-{$ifdef CPUx86_64}
-{$define RTSIGACTION}
-{$endif CPUx86_64}
-
 function Fpsigaction(sig: cint; act : psigactionrec; oact : psigactionrec): cint; [public, alias : 'FPC_SYSC_SIGACTION'];
 function Fpsigaction(sig: cint; act : psigactionrec; oact : psigactionrec): cint; [public, alias : 'FPC_SYSC_SIGACTION'];
 
 
 {
 {
@@ -452,6 +451,27 @@ begin
   Fpreadlink:=do_syscall(syscall_nr_readlink, TSysParam(name),TSysParam(linkname),maxlen);
   Fpreadlink:=do_syscall(syscall_nr_readlink, TSysParam(name),TSysParam(linkname),maxlen);
 end;
 end;
 
 
+
+function FPSigProcMask(how:cint;nset : psigset;oset : psigset):cint; [public, alias : 'FPC_SYSC_SIGPROCMASK'];
+
+{
+  Change the list of currently blocked signals.
+  How determines which signals will be blocked :
+   SigBlock   : Add SSet to the current list of blocked signals
+   SigUnBlock : Remove the signals in SSet from the list of blocked signals.
+   SigSetMask : Set the list of blocked signals to SSet
+  if OldSSet is non-null, the old set will be saved there.
+}
+
+begin
+{$ifdef RTSIGACTION}
+  FPsigprocmask:=do_syscall(syscall_nr_rt_sigprocmask,TSysParam(how),TSysParam(nset),TSysParam(oset),TSysParam(8));
+{$else RTSIGACTION}
+  FPsigprocmask:=do_syscall(syscall_nr_sigprocmask,TSysParam(how),TSysParam(nset),TSysParam(oset),TSysParam(8));
+{$endif RTSIGACTION}
+end;
+
+
 Function FpNanoSleep(req : ptimespec;rem : ptimespec):cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
 Function FpNanoSleep(req : ptimespec;rem : ptimespec):cint; [public, alias : 'FPC_SYSC_NANOSLEEP'];
 begin
 begin
   FpNanoSleep:=Do_SysCall(syscall_nr_nanosleep,TSysParam(req),TSysParam(rem));
   FpNanoSleep:=Do_SysCall(syscall_nr_nanosleep,TSysParam(req),TSysParam(rem));
@@ -509,7 +529,10 @@ end;
 
 
 {
 {
  $Log$
  $Log$
- Revision 1.23  2004-04-27 20:47:00  florian
+ Revision 1.24  2004-05-01 15:59:17  florian
+   * x86_64 exception handling fixed
+
+ Revision 1.23  2004/04/27 20:47:00  florian
    * tried to fix x86-64 signal handling
    * tried to fix x86-64 signal handling
 
 
  Revision 1.22  2004/04/25 07:18:49  florian
  Revision 1.22  2004/04/25 07:18:49  florian

+ 50 - 3
rtl/linux/signal.inc

@@ -242,9 +242,53 @@ type
 {$endif cpusparc}
 {$endif cpusparc}
 
 
 {$ifdef cpux86_64}
 {$ifdef cpux86_64}
-{ get it from glibc/sysdeps/unix/sysv/linux/x86_64/sys/uncontext.h }
+
+  p_fpstate = ^_fpstate;
+  _fpstate = packed record
+    cwd,
+    swd,
+    twd,    // Note this is not the same as the 32bit/x87/FSAVE twd
+    fop : word;
+    rip,
+    rdp : qword;
+    mxcsr,
+    mxcsr_mask : dword;
+    st_space : array[0..31] of dword;  // 8*16 bytes for each FP-reg
+    xmm_space : array[0..63] of dword; // 16*16 bytes for each XMM-reg
+    reserved2 : array[0..23] of dword;
+  end;
+
   PSigContextRec = ^SigContextRec;
   PSigContextRec = ^SigContextRec;
-  SigContextRec = record
+  SigContextRec = packed record
+    __pad00 : array[0..4] of qword;
+    r8,
+    r9,
+    r10,
+    r11,
+    r12,
+    r13,
+    r14,
+    r15,
+    rdi,
+    rsi,
+    rbp,
+    rbx,
+    rdx,
+    rax,
+    rcx,
+    rsp,
+    rip,
+    eflags : qword;
+    cs,
+    gs,
+    fs,
+    __pad0 : word;
+    err,
+    trapno,
+    oldmask,
+    cr2 : qword;
+    fpstate : p_fpstate;       // zero when no FPU context */
+    reserved1 : array[0..7] of qword;
   end;
   end;
 {$endif cpux86_64}
 {$endif cpux86_64}
 
 
@@ -376,7 +420,10 @@ type
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.18  2004-04-27 20:47:00  florian
+  Revision 1.19  2004-05-01 15:59:17  florian
+    * x86_64 exception handling fixed
+
+  Revision 1.18  2004/04/27 20:47:00  florian
     * tried to fix x86-64 signal handling
     * tried to fix x86-64 signal handling
 
 
   Revision 1.17  2004/03/27 14:35:13  florian
   Revision 1.17  2004/03/27 14:35:13  florian

+ 46 - 33
rtl/linux/x86_64/sighnd.inc

@@ -20,31 +20,43 @@
 const
 const
   FPU_All = $7f;
   FPU_All = $7f;
 
 
-function GetFPUState(const SigContext : SigContextRec) : longint;
-begin
-{!!!!!!!
-  if assigned(SigContext.fpstate) then
-    GetfpuState:=SigContext.fpstate^.sw;
-{$ifdef SYSTEM_DEBUG}
-  writeln('xx:',sigcontext.en_tw,' ',sigcontext.en_cw);
-{$endif SYSTEM_DEBUG}
-{$ifdef SYSTEM_DEBUG}
-  Writeln(stderr,'FpuState = ',GetFpuState);
-{$endif SYSTEM_DEBUG}
-}
-end;
-
-procedure SignalToRunerror(Sig: longint; SigContext: SigContextRec); cdecl;
+function GetFPUState(const SigContext : SigContextRec) : word;
+  begin
+    if assigned(SigContext.fpstate) then
+      GetfpuState:=SigContext.fpstate^.swd;
+  {$ifdef SYSTEM_DEBUG}
+    writeln('xx:',sigcontext.en_tw,' ',sigcontext.en_cw);
+  {$endif SYSTEM_DEBUG}
+  {$ifdef SYSTEM_DEBUG}
+    Writeln(stderr,'FpuState = ',result);
+  {$endif SYSTEM_DEBUG}
+  end;
 
 
+function  reenable_signal(sig : longint) : boolean;
 var
 var
-  res,fpustate : word;
+  e,olde : TSigSet;
+  i,j : byte;
 begin
 begin
-  res:=0;
-  case sig of
-    SIGFPE :
-          begin
-    { this is not allways necessary but I don't know yet
-      how to tell if it is or not PM }
+  fillchar(e,sizeof(e),#0);
+  { set is 1 based PM }
+  dec(sig);
+  i:=sig mod 32;
+  j:=sig div 32;
+  e[j]:=1 shl i;
+  fpsigprocmask(SIG_UNBLOCK,@e,nil);
+  reenable_signal:=geterrno=0;
+end;
+
+procedure SignalToRunerror(sig : longint; SigContext: SigContextRec); cdecl;
+  var
+    res,fpustate : word;
+  begin
+    res:=0;
+    case sig of
+      SIGFPE :
+        begin
+          { this is not allways necessary but I don't know yet
+            how to tell if it is or not PM }
           res:=200;
           res:=200;
           fpustate:=GetFPUState(SigContext);
           fpustate:=GetFPUState(SigContext);
           if (FpuState and FPU_All) <> 0 then
           if (FpuState and FPU_All) <> 0 then
@@ -65,23 +77,24 @@ begin
               else
               else
                 res:=207;  {'Coprocessor Error'}
                 res:=207;  {'Coprocessor Error'}
             end;
             end;
-            sysResetFPU;
+            SysResetFPU;
         end;
         end;
-    SIGILL,
-    SIGBUS,
-    SIGSEGV :
+      SIGILL,
+      SIGBUS,
+      SIGSEGV:
         res:=216;
         res:=216;
+    end;
+    reenable_signal(sig);
+    if res<>0 then
+      HandleErrorAddrFrame(res,pointer(SigContext.rip),pointer(SigContext.rbp));
   end;
   end;
-{ give runtime error at the position where the signal was raised }
-{!!!!
-  if res<>0 then
-    HandleErrorAddrFrame(res,pointer(SigContext.eip),pointer(SigContext.ebp));
-}
-end;
 
 
 {
 {
   $Log$
   $Log$
-  Revision 1.1  2004-02-05 01:16:12  florian
+  Revision 1.2  2004-05-01 15:59:17  florian
+    * x86_64 exception handling fixed
+
+  Revision 1.1  2004/02/05 01:16:12  florian
     + completed x86-64/linux system unit
     + completed x86-64/linux system unit
 
 
   Revision 1.2  2003/11/01 01:58:11  marco
   Revision 1.2  2003/11/01 01:58:11  marco

+ 11 - 1
rtl/x86_64/x86_64.inc

@@ -343,9 +343,19 @@ const
   FPU_StackOverflow = $40;
   FPU_StackOverflow = $40;
   FPU_ExceptionMask = $ff;
   FPU_ExceptionMask = $ff;
 
 
+{$define FPC_SYSTEM_HAS_SYSRESETFPU}
+Procedure SysResetFPU;assembler;{$ifdef SYSTEMINLINE}inline;{$endif}
+asm
+    fninit
+    fldcw   fpucw
+end;
+
 {
 {
   $Log$
   $Log$
-  Revision 1.11  2004-04-29 19:50:13  peter
+  Revision 1.12  2004-05-01 15:59:17  florian
+    * x86_64 exception handling fixed
+
+  Revision 1.11  2004/04/29 19:50:13  peter
     * x86-64 fixes
     * x86-64 fixes
 
 
   Revision 1.10  2004/04/26 15:55:01  peter
   Revision 1.10  2004/04/26 15:55:01  peter