Mirror of BoringSSL (grpc依赖)
https://boringssl.googlesource.com/boringssl
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
216 lines
6.2 KiB
216 lines
6.2 KiB
#!/usr/bin/env perl |
|
# Copyright (c) 2019, Google Inc. |
|
# |
|
# Permission to use, copy, modify, and/or distribute this software for any |
|
# purpose with or without fee is hereby granted, provided that the above |
|
# copyright notice and this permission notice appear in all copies. |
|
# |
|
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|
# SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|
# OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|
# CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
|
|
# This file defines helper functions for crypto/test/abi_test.h on aarch64. See |
|
# that header for details on how to use this. |
|
# |
|
# For convenience, this file is linked into libcrypto, where consuming builds |
|
# already support architecture-specific sources. The static linker should drop |
|
# this code in non-test binaries. This includes a shared library build of |
|
# libcrypto, provided --gc-sections (ELF), -dead_strip (iOS), or equivalent is |
|
# used. |
|
# |
|
# References: |
|
# |
|
# AAPCS64: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf |
|
# iOS ARM64: https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html |
|
|
|
use strict; |
|
|
|
my $flavour = shift; |
|
my $output = shift; |
|
if ($flavour =~ /\./) { $output = $flavour; undef $flavour; } |
|
|
|
$0 =~ m/(.*[\/\\])[^\/\\]+$/; |
|
my $dir = $1; |
|
my $xlate; |
|
( $xlate="${dir}arm-xlate.pl" and -f $xlate ) or |
|
( $xlate="${dir}../../perlasm/arm-xlate.pl" and -f $xlate) or |
|
die "can't locate arm-xlate.pl"; |
|
|
|
open OUT, "| \"$^X\" \"$xlate\" $flavour \"$output\""; |
|
*STDOUT = *OUT; |
|
|
|
my ($func, $state, $argv, $argc) = ("x0", "x1", "x2", "x3"); |
|
my $code = <<____; |
|
#include <openssl/arm_arch.h> |
|
|
|
.text |
|
|
|
// abi_test_trampoline loads callee-saved registers from |state|, calls |func| |
|
// with |argv|, then saves the callee-saved registers into |state|. It returns |
|
// the result of |func|. The |unwind| argument is unused. |
|
// uint64_t abi_test_trampoline(void (*func)(...), CallerState *state, |
|
// const uint64_t *argv, size_t argc, |
|
// uint64_t unwind); |
|
.type abi_test_trampoline, %function |
|
.globl abi_test_trampoline |
|
.align 4 |
|
abi_test_trampoline: |
|
.Labi_test_trampoline_begin: |
|
AARCH64_SIGN_LINK_REGISTER |
|
// Stack layout (low to high addresses) |
|
// x29,x30 (16 bytes) |
|
// d8-d15 (64 bytes) |
|
// x19-x28 (80 bytes) |
|
// $state (8 bytes) |
|
// padding (8 bytes) |
|
stp x29, x30, [sp, #-176]! |
|
mov x29, sp |
|
|
|
// Saved callee-saved registers and |state|. |
|
stp d8, d9, [sp, #16] |
|
stp d10, d11, [sp, #32] |
|
stp d12, d13, [sp, #48] |
|
stp d14, d15, [sp, #64] |
|
stp x19, x20, [sp, #80] |
|
stp x21, x22, [sp, #96] |
|
stp x23, x24, [sp, #112] |
|
stp x25, x26, [sp, #128] |
|
stp x27, x28, [sp, #144] |
|
str $state, [sp, #160] |
|
|
|
// Load registers from |state|, with the exception of x29. x29 is the |
|
// frame pointer and also callee-saved, but AAPCS64 allows platforms to |
|
// mandate that x29 always point to a frame. iOS64 does so, which means |
|
// we cannot fill x29 with entropy without violating ABI rules |
|
// ourselves. x29 is tested separately below. |
|
ldp d8, d9, [$state], #16 |
|
ldp d10, d11, [$state], #16 |
|
ldp d12, d13, [$state], #16 |
|
ldp d14, d15, [$state], #16 |
|
ldp x19, x20, [$state], #16 |
|
ldp x21, x22, [$state], #16 |
|
ldp x23, x24, [$state], #16 |
|
ldp x25, x26, [$state], #16 |
|
ldp x27, x28, [$state], #16 |
|
|
|
// Move parameters into temporary registers. |
|
mov x9, $func |
|
mov x10, $argv |
|
mov x11, $argc |
|
|
|
// Load parameters into registers. |
|
cbz x11, .Largs_done |
|
ldr x0, [x10], #8 |
|
subs x11, x11, #1 |
|
b.eq .Largs_done |
|
ldr x1, [x10], #8 |
|
subs x11, x11, #1 |
|
b.eq .Largs_done |
|
ldr x2, [x10], #8 |
|
subs x11, x11, #1 |
|
b.eq .Largs_done |
|
ldr x3, [x10], #8 |
|
subs x11, x11, #1 |
|
b.eq .Largs_done |
|
ldr x4, [x10], #8 |
|
subs x11, x11, #1 |
|
b.eq .Largs_done |
|
ldr x5, [x10], #8 |
|
subs x11, x11, #1 |
|
b.eq .Largs_done |
|
ldr x6, [x10], #8 |
|
subs x11, x11, #1 |
|
b.eq .Largs_done |
|
ldr x7, [x10], #8 |
|
|
|
.Largs_done: |
|
blr x9 |
|
|
|
// Reload |state| and store registers. |
|
ldr $state, [sp, #160] |
|
stp d8, d9, [$state], #16 |
|
stp d10, d11, [$state], #16 |
|
stp d12, d13, [$state], #16 |
|
stp d14, d15, [$state], #16 |
|
stp x19, x20, [$state], #16 |
|
stp x21, x22, [$state], #16 |
|
stp x23, x24, [$state], #16 |
|
stp x25, x26, [$state], #16 |
|
stp x27, x28, [$state], #16 |
|
|
|
// |func| is required to preserve x29, the frame pointer. We cannot load |
|
// random values into x29 (see comment above), so compare it against the |
|
// expected value and zero the field of |state| if corrupted. |
|
mov x9, sp |
|
cmp x29, x9 |
|
b.eq .Lx29_ok |
|
str xzr, [$state] |
|
|
|
.Lx29_ok: |
|
// Restore callee-saved registers. |
|
ldp d8, d9, [sp, #16] |
|
ldp d10, d11, [sp, #32] |
|
ldp d12, d13, [sp, #48] |
|
ldp d14, d15, [sp, #64] |
|
ldp x19, x20, [sp, #80] |
|
ldp x21, x22, [sp, #96] |
|
ldp x23, x24, [sp, #112] |
|
ldp x25, x26, [sp, #128] |
|
ldp x27, x28, [sp, #144] |
|
|
|
ldp x29, x30, [sp], #176 |
|
AARCH64_VALIDATE_LINK_REGISTER |
|
ret |
|
.size abi_test_trampoline,.-abi_test_trampoline |
|
____ |
|
|
|
# abi_test_clobber_* zeros the corresponding register. These are used to test |
|
# the ABI-testing framework. |
|
foreach (0..29) { |
|
# x18 is the platform register and off limits. |
|
next if ($_ == 18); |
|
$code .= <<____; |
|
.type abi_test_clobber_x$_, %function |
|
.globl abi_test_clobber_x$_ |
|
.align 4 |
|
abi_test_clobber_x$_: |
|
AARCH64_VALID_CALL_TARGET |
|
mov x$_, xzr |
|
ret |
|
.size abi_test_clobber_x$_,.-abi_test_clobber_x$_ |
|
____ |
|
} |
|
foreach (0..31) { |
|
$code .= <<____; |
|
.type abi_test_clobber_d$_, %function |
|
.globl abi_test_clobber_d$_ |
|
.align 4 |
|
abi_test_clobber_d$_: |
|
AARCH64_VALID_CALL_TARGET |
|
fmov d$_, xzr |
|
ret |
|
.size abi_test_clobber_d$_,.-abi_test_clobber_d$_ |
|
____ |
|
} |
|
|
|
# abi_test_clobber_v*_upper clobbers only the upper half of v*. AAPCS64 only |
|
# requires the lower half (d*) be preserved. |
|
foreach (8..15) { |
|
$code .= <<____; |
|
.type abi_test_clobber_v${_}_upper, %function |
|
.globl abi_test_clobber_v${_}_upper |
|
.align 4 |
|
abi_test_clobber_v${_}_upper: |
|
AARCH64_VALID_CALL_TARGET |
|
fmov v${_}.d[1], xzr |
|
ret |
|
.size abi_test_clobber_v${_}_upper,.-abi_test_clobber_v${_}_upper |
|
____ |
|
} |
|
|
|
print $code; |
|
close STDOUT or die "error closing STDOUT: $!";
|
|
|