Browse Source

+ Support .seh_handler directive

git-svn-id: trunk@19365 -
sergei 14 years ago
parent
commit
9eb451756b
3 changed files with 36 additions and 17 deletions
  1. 17 10
      compiler/aasmtai.pas
  2. 8 2
      compiler/aggas.pas
  3. 11 5
      compiler/x86_64/win64unw.pas

+ 17 - 10
compiler/aasmtai.pas

@@ -298,12 +298,12 @@ interface
         'extern','nasm_import', 'tc', 'reference',
         'no_dead_strip','weak_reference','lazy_reference','weak_definition'
       );
-      sehdirectivestr : array[TAsmSehDirective] of string[15]=(
-        'seh_proc','seh_endproc',
-        'seh_endprologue','seh_handler','seh_handlerdata',
-        'seh_eh','seh_32','seh_no32',
-        'seh_setframe','seh_stackalloc','seh_pushreg',
-        'seh_savereg','seh_savexmm','seh_pushframe'
+      sehdirectivestr : array[TAsmSehDirective] of string[16]=(
+        '.seh_proc','.seh_endproc',
+        '.seh_endprologue','.seh_handler','.seh_handlerdata',
+        '.seh_eh','.seh_32','seh_no32',
+        '.seh_setframe','.seh_stackalloc','.seh_pushreg',
+        '.seh_savereg','.seh_savexmm','.seh_pushframe'
       );
 
     type
@@ -686,7 +686,7 @@ interface
         TSehDirectiveData=record
         case typ: TSehDirectiveDatatype of
           sd_none: ();
-          sd_string: (name:pshortstring);
+          sd_string: (name:pshortstring;flags:byte);
           sd_reg,sd_offset,sd_regoffset: (reg:TRegister;offset:dword);
         end;
 
@@ -2542,7 +2542,7 @@ implementation
         sd_string,     { proc }
         sd_none,       { endproc }
         sd_none,       { endprologue }
-        sd_none,       { TODO: handler }
+        sd_string,     { handler }
         sd_none,       { handlerdata }
         sd_none,sd_none,sd_none,  { eh, 32, no32 }
         sd_regoffset,  { setframe }
@@ -2595,7 +2595,10 @@ implementation
         case data.typ of
           sd_none: ;
           sd_string:
-            data.name:=stringdup(ppufile.getstring);
+            begin
+              data.name:=stringdup(ppufile.getstring);
+              data.flags:=ppufile.getbyte;
+            end;
 
           sd_reg,sd_offset,sd_regoffset:
             begin
@@ -2621,7 +2624,11 @@ implementation
         case data.typ of
           sd_none: ;
           sd_string:
-            ppufile.putstring(data.name^);
+            begin
+              ppufile.putstring(data.name^);
+              ppufile.putbyte(data.flags);
+            end;
+
           sd_reg,sd_offset,sd_regoffset:
             begin
               ppufile.putdata(data.reg,sizeof(TRegister));

+ 8 - 2
compiler/aggas.pas

@@ -1239,11 +1239,17 @@ implementation
            ait_seh_directive :
              begin
 {$ifdef TEST_WIN64_UNWIND}
-               AsmWrite('.'+sehdirectivestr[tai_seh_directive(hp).kind]);
+               AsmWrite(sehdirectivestr[tai_seh_directive(hp).kind]);
                case tai_seh_directive(hp).datatype of
                  sd_none:;
                  sd_string:
-                   AsmWrite(' '+tai_seh_directive(hp).data.name^);
+                   begin
+                     AsmWrite(' '+tai_seh_directive(hp).data.name^);
+                     if (tai_seh_directive(hp).data.flags and 1)<>0 then
+                       AsmWrite(',@except');
+                     if (tai_seh_directive(hp).data.flags and 2)<>0 then
+                       AsmWrite(',@unwind');
+                   end;
                  sd_reg:
                    AsmWrite(' '+gas_regname(tai_seh_directive(hp).data.reg));
                  sd_offset:

+ 11 - 5
compiler/x86_64/win64unw.pas

@@ -33,6 +33,7 @@ type
   private
     FFrameOffs, FFrameReg: Integer;
     FFlags: Integer;
+    FHandler: TObjSymbol;
     FCount: Integer;
     FElements:TLinkedList;
     FFrameStartSym:TObjSymbol;
@@ -179,8 +180,6 @@ var
   xdatasym,pdatasym: TObjSymbol;
   zero: word;
 begin
-{  if FCount=0 then
-     InternalError(2011072308); }
   if FCount>255 then
     InternalError(2011072301);
 
@@ -230,7 +229,8 @@ begin
   zero:=0;
   if odd(FCount) then
     objdata.writebytes(zero,2);
-  { TODO: handler rva and data should follow if flags specify a handler }
+  if Assigned(FHandler) then
+    objdata.writereloc(0,sizeof(longint),FHandler,RELOC_RVA);
 
   FElements.Clear;
 
@@ -255,6 +255,7 @@ begin
   FFrameReg:=0;
   FFrameOffs:=0;
   FPrologueEndPos:=0;
+  FHandler:=nil;
 end;
 
 procedure TWin64CFI.end_frame(objdata:TObjData);
@@ -263,6 +264,7 @@ begin
     internalerror(2011072307);
   generate_code(objdata);
   FFrameStartSym:=nil;
+  FHandler:=nil;
   stringdispose(FName);
 end;
 
@@ -336,9 +338,13 @@ begin
       current_unw.end_frame(objdata);
     ash_endprologue:
       current_unw.end_prologue(objdata);
-    ash_handler:     {TBD};
+    ash_handler:
+      begin
+        current_unw.FHandler:=objdata.symbolref(data.name^);
+        current_unw.FFlags:=data.flags;
+      end;
     ash_handlerdata: {TBD};
-    ash_eh,ash_32,ash_no32: ; { there are not for x86_64 }
+    ash_eh,ash_32,ash_no32: ; { these are not for x86_64 }
     ash_setframe:
       current_unw.set_frame(objdata,data.reg,data.offset);
     ash_stackalloc: