crypto/perlasm/x86_64-xlate.pl: detect GNU as to deal with quirks
[openssl.git] / crypto / perlasm / x86_64-xlate.pl
index f8380f2e9cfa9fb48e78e158e1bc45b32be45f4b..197bc48873cabe628e54e208b3421dfbb4434d3d 100755 (executable)
@@ -1,7 +1,7 @@
 #! /usr/bin/env perl
 # Copyright 2005-2018 The OpenSSL Project Authors. All Rights Reserved.
 #
-# Licensed under the OpenSSL license (the "License").  You may not use
+# Licensed under the Apache License 2.0 (the "License").  You may not use
 # this file except in compliance with the License.  You can obtain a copy
 # in the file LICENSE in the source distribution or at
 # https://www.openssl.org/source/license.html
@@ -83,6 +83,10 @@ my $PTR=" PTR";
 my $nasmref=2.03;
 my $nasm=0;
 
+# GNU as indicator, as opposed to $gas, which indicates acceptable
+# syntax
+my $gnuas=0;
+
 if    ($flavour eq "mingw64")  { $gas=1; $elf=0; $win64=1;
                                  $prefix=`echo __USER_LABEL_PREFIX__ | $ENV{CC} -E -P -`;
                                  $prefix =~ s|\R$||; # Better chomp
@@ -100,6 +104,46 @@ elsif (!$gas)
     $elf=0;
     $decor="\$L\$";
 }
+# Find out if we're using GNU as
+elsif (`$ENV{CC} -Wa,-v -c -o /dev/null -x assembler /dev/null 2>&1`
+               =~ /GNU assembler version ([2-9]\.[0-9]+)/)
+{
+    $gnuas=1;
+}
+
+my $cet_property;
+if ($flavour =~ /elf/) {
+       # Always generate .note.gnu.property section for ELF outputs to
+       # mark Intel CET support since all input files must be marked
+       # with Intel CET support in order for linker to mark output with
+       # Intel CET support.
+       my $p2align=3; $p2align=2 if ($flavour eq "elf32");
+       my $section='.note.gnu.property, #alloc';
+       $section='".note.gnu.property", "a"' if $gnuas;
+       $cet_property = <<_____;
+       .section $section
+       .p2align $p2align
+       .long 1f - 0f
+       .long 4f - 1f
+       .long 5
+0:
+       # "GNU" encoded with .byte, since .asciz isn't supported
+       # on Solaris.
+       .byte 0x47
+       .byte 0x4e
+       .byte 0x55
+       .byte 0
+1:
+       .p2align $p2align
+       .long 0xc0000002
+       .long 3f - 2f
+2:
+       .long 3
+3:
+       .p2align $p2align
+4:
+_____
+}
 
 my $current_segment;
 my $current_function;
@@ -541,6 +585,7 @@ my %globals;
        );
 
     my ($cfa_reg, $cfa_rsp);
+    my @cfa_stack;
 
     # [us]leb128 format is variable-length integer representation base
     # 2^128, with most significant bit of each byte being 0 denoting
@@ -648,7 +693,13 @@ my %globals;
            # why it starts with -8. Recall that CFA is top of caller's
            # stack...
            /startproc/ && do { ($cfa_reg, $cfa_rsp) = ("%rsp", -8); last; };
-           /endproc/   && do { ($cfa_reg, $cfa_rsp) = ("%rsp",  0); last; };
+           /endproc/   && do { ($cfa_reg, $cfa_rsp) = ("%rsp",  0);
+                               # .cfi_remember_state directives that are not
+                               # matched with .cfi_restore_state are
+                               # unnecessary.
+                               die "unpaired .cfi_remember_state" if (@cfa_stack);
+                               last;
+                             };
            /def_cfa_register/
                        && do { $cfa_reg = $$line; last; };
            /def_cfa_offset/
@@ -688,6 +739,14 @@ my %globals;
                                                      cfa_expression($$line)));
                                last;
                              };
+           /remember_state/
+                       && do { push @cfa_stack, [$cfa_reg, $cfa_rsp];
+                               last;
+                             };
+           /restore_state/
+                       && do { ($cfa_reg, $cfa_rsp) = @{pop @cfa_stack};
+                               last;
+                             };
            }
 
            $self->{value} = ".cfi_$dir\t$$line" if ($dir);
@@ -1198,10 +1257,11 @@ while(defined(my $line=<>)) {
     print $line,"\n";
 }
 
+print "$cet_property"                  if ($cet_property);
 print "\n$current_segment\tENDS\n"     if ($current_segment && $masm);
 print "END\n"                          if ($masm);
 
-close STDOUT;
+close STDOUT or die "error closing STDOUT: $!;"
 
 \f#################################################
 # Cross-reference x86_64 ABI "card"