#! /usr/bin/env perl
-# Copyright 2005-2016 The OpenSSL Project Authors. All Rights Reserved.
+# 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
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
$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;
}
sprintf "\$%s",$self->{value};
} else {
- $self->{value} =~ s/0x([0-9a-f]+)/0$1h/ig if ($masm);
- sprintf "%s",$self->{value};
+ my $value = $self->{value};
+ $value =~ s/0x([0-9a-f]+)/0$1h/ig if ($masm);
+ sprintf "%s",$value;
}
}
}
}
# if base register is %rbp or %r13, see if it's possible to
- # flip base and ingex registers [for better performance]
+ # flip base and index registers [for better performance]
if (!$self->{label} && $self->{index} && $self->{scale}==1 &&
$self->{base} =~ /(rbp|r13)/) {
$self->{base} = $self->{index}; $self->{index} = $1;
}
}
}
-{ package expr; # pick up expressioins
+{ package expr; # pick up expressions
sub re {
my ($class, $line, $opcode) = @_;
my $self = {};
);
# Following constants are defined in x86_64 ABI supplement, for
- # example avaiable at https://www.uclibc.org/docs/psABI-x86_64.pdf,
+ # example available at https://www.uclibc.org/docs/psABI-x86_64.pdf,
# see section 3.7 "Stack Unwind Algorithm".
my %DW_reg_idx = (
"%rax"=>0, "%rdx"=>1, "%rcx"=>2, "%rbx"=>3,
);
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
- # *last* most significat digit. See "Variable Length Data" in the
+ # *last* most significant digit. See "Variable Length Data" in the
# DWARF specification, numbered 7.6 at least in versions 3 and 4.
sub sleb128 {
use integer; # get right shift extend sign
foreach my $token (split(/,\s*/,$line)) {
if ($token =~ /^%r/) {
push @ret,reg($token);
+ } elsif ($token =~ /((?:0x)?[0-9a-f]+)\((%r\w+)\)/) {
+ push @ret,reg("$2+$1");
} elsif ($token =~ /(\w+):(\-?(?:0x)?[0-9a-f]+)(U?)/i) {
my $i = 1*eval($2);
push @ret,$DW_OP_complex{$1}, ($3 ? uleb128($i) : sleb128($i));
my $self = {};
my $ret;
- if ($$line =~ s/^\s*\.cfi_(\w+)\s+//) {
+ if ($$line =~ s/^\s*\.cfi_(\w+)\s*//) {
bless $self,$class;
$ret = $self;
undef $self->{value};
# 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/
&& do { $cfa_rsp -= 1*eval($$line) if ($cfa_reg eq "%rsp");
last;
};
- /def_cfa/ && do { if ($$line =~ /(%r\w+)\s*,\s*(\.+)/) {
+ /def_cfa/ && do { if ($$line =~ /(%r\w+)\s*,\s*(.+)/) {
$cfa_reg = $1;
$cfa_rsp = -1*eval($2) if ($cfa_reg eq "%rsp");
}
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);
$var=~s/^(0b[0-1]+)/oct($1)/eig;
$var=~s/^0x([0-9a-f]+)/0$1h/ig if ($masm);
if ($sz eq "D" && ($current_segment=~/.[px]data/ || $dir eq ".rva"))
- { $var=~s/([_a-z\$\@][_a-z0-9\$\@]*)/$nasm?"$1 wrt ..imagebase":"imagerel $1"/egi; }
+ { $var=~s/^([_a-z\$\@][_a-z0-9\$\@]*)/$nasm?"$1 wrt ..imagebase":"imagerel $1"/egi; }
$var;
};
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"
# the area above user stack pointer in true asynchronous manner...
#
# All the above means that if assembler programmer adheres to Unix
-# register and stack layout, but disregards the "red zone" existense,
+# register and stack layout, but disregards the "red zone" existence,
# it's possible to use following prologue and epilogue to "gear" from
# Unix to Win64 ABI in leaf functions with not more than 6 arguments.
#
#
# (*) Note that we're talking about run-time, not debug-time. Lack of
# unwind information makes debugging hard on both Windows and
-# Unix. "Unlike" referes to the fact that on Unix signal handler
+# Unix. "Unlike" refers to the fact that on Unix signal handler
# will always be invoked, core dumped and appropriate exit code
# returned to parent (for user notification).