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.
560 lines
24 KiB
560 lines
24 KiB
5 years ago
|
/* Copyright (c) 2018, 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. */
|
||
|
|
||
|
#ifndef OPENSSL_HEADER_ABI_TEST_H
|
||
|
#define OPENSSL_HEADER_ABI_TEST_H
|
||
|
|
||
|
#include <gtest/gtest.h>
|
||
|
|
||
|
#include <string>
|
||
|
#include <type_traits>
|
||
|
#include <vector>
|
||
|
|
||
|
#include <openssl/base.h>
|
||
|
|
||
|
#include "../internal.h"
|
||
|
|
||
|
|
||
|
// abi_test provides routines for verifying that functions satisfy platform ABI
|
||
|
// requirements.
|
||
|
namespace abi_test {
|
||
|
|
||
|
// Result stores the result of an ABI test.
|
||
|
struct Result {
|
||
|
bool ok() const { return errors.empty(); }
|
||
|
|
||
|
std::vector<std::string> errors;
|
||
|
};
|
||
|
|
||
|
namespace internal {
|
||
|
|
||
|
// DeductionGuard wraps |T| in a template, so that template argument deduction
|
||
|
// does not apply to it. This may be used to force C++ to deduce template
|
||
|
// arguments from another parameter.
|
||
|
template <typename T>
|
||
|
struct DeductionGuard {
|
||
|
using Type = T;
|
||
|
};
|
||
|
|
||
|
// Reg128 contains storage space for a 128-bit register.
|
||
|
struct alignas(16) Reg128 {
|
||
|
bool operator==(const Reg128 &x) const { return x.lo == lo && x.hi == hi; }
|
||
|
bool operator!=(const Reg128 &x) const { return !((*this) == x); }
|
||
|
uint64_t lo, hi;
|
||
|
};
|
||
|
|
||
|
// LOOP_CALLER_STATE_REGISTERS is a macro that iterates over all registers the
|
||
|
// callee is expected to save for the caller, with the exception of the stack
|
||
|
// pointer. The stack pointer is tested implicitly by the function successfully
|
||
|
// returning at all.
|
||
|
#if defined(OPENSSL_X86_64)
|
||
|
|
||
|
// References:
|
||
|
// SysV64: https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf
|
||
|
// Win64: https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions?view=vs-2017#register-usage
|
||
|
#if defined(OPENSSL_WINDOWS)
|
||
|
#define LOOP_CALLER_STATE_REGISTERS() \
|
||
|
CALLER_STATE_REGISTER(uint64_t, rbx) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, rbp) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, rdi) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, rsi) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r12) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r13) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r14) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r15) \
|
||
|
CALLER_STATE_REGISTER(Reg128, xmm6) \
|
||
|
CALLER_STATE_REGISTER(Reg128, xmm7) \
|
||
|
CALLER_STATE_REGISTER(Reg128, xmm8) \
|
||
|
CALLER_STATE_REGISTER(Reg128, xmm9) \
|
||
|
CALLER_STATE_REGISTER(Reg128, xmm10) \
|
||
|
CALLER_STATE_REGISTER(Reg128, xmm11) \
|
||
|
CALLER_STATE_REGISTER(Reg128, xmm12) \
|
||
|
CALLER_STATE_REGISTER(Reg128, xmm13) \
|
||
|
CALLER_STATE_REGISTER(Reg128, xmm14) \
|
||
|
CALLER_STATE_REGISTER(Reg128, xmm15)
|
||
|
#else
|
||
|
#define LOOP_CALLER_STATE_REGISTERS() \
|
||
|
CALLER_STATE_REGISTER(uint64_t, rbx) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, rbp) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r12) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r13) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r14) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r15)
|
||
|
#endif // OPENSSL_WINDOWS
|
||
|
|
||
|
#elif defined(OPENSSL_X86)
|
||
|
|
||
|
// References:
|
||
|
// SysV32: https://uclibc.org/docs/psABI-i386.pdf and
|
||
|
// Win32: https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions?view=vs-2017
|
||
|
#define LOOP_CALLER_STATE_REGISTERS() \
|
||
|
CALLER_STATE_REGISTER(uint32_t, esi) \
|
||
|
CALLER_STATE_REGISTER(uint32_t, edi) \
|
||
|
CALLER_STATE_REGISTER(uint32_t, ebx) \
|
||
|
CALLER_STATE_REGISTER(uint32_t, ebp)
|
||
|
|
||
|
#elif defined(OPENSSL_ARM)
|
||
|
|
||
|
// References:
|
||
|
// AAPCS: https://developer.arm.com/docs/ihi0042/latest
|
||
|
// iOS32: https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
|
||
|
// Linux: http://sourcery.mentor.com/sgpp/lite/arm/portal/kbattach142/arm_gnu_linux_%20abi.pdf
|
||
|
//
|
||
|
// ARM specifies a common calling convention, except r9 is left to the platform.
|
||
|
// Linux treats r9 as callee-saved, while iOS 3+ treats it as caller-saved. Most
|
||
|
// of our assembly treats it as callee-saved to be uniform, but we match the
|
||
|
// platform to avoid false positives when testing compiler-generated output.
|
||
|
#define LOOP_CALLER_STATE_REGISTERS_PRE_R9() \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d8) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d9) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d10) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d11) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d12) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d13) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d14) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d15) \
|
||
|
CALLER_STATE_REGISTER(uint32_t, r4) \
|
||
|
CALLER_STATE_REGISTER(uint32_t, r5) \
|
||
|
CALLER_STATE_REGISTER(uint32_t, r6) \
|
||
|
CALLER_STATE_REGISTER(uint32_t, r7) \
|
||
|
CALLER_STATE_REGISTER(uint32_t, r8)
|
||
|
#define LOOP_CALLER_STATE_REGISTERS_POST_R9() \
|
||
|
CALLER_STATE_REGISTER(uint32_t, r10) \
|
||
|
CALLER_STATE_REGISTER(uint32_t, r11)
|
||
|
#if defined(OPENSSL_APPLE)
|
||
|
#define LOOP_CALLER_STATE_REGISTERS() \
|
||
|
LOOP_CALLER_STATE_REGISTERS_PRE_R9() \
|
||
|
LOOP_CALLER_STATE_REGISTERS_POST_R9()
|
||
|
#else // !OPENSSL_APPLE
|
||
|
#define LOOP_CALLER_STATE_REGISTERS() \
|
||
|
LOOP_CALLER_STATE_REGISTERS_PRE_R9() \
|
||
|
CALLER_STATE_REGISTER(uint32_t, r9) \
|
||
|
LOOP_CALLER_STATE_REGISTERS_POST_R9()
|
||
|
#endif // OPENSSL_APPLE
|
||
|
|
||
|
#elif defined(OPENSSL_AARCH64)
|
||
|
|
||
|
// References:
|
||
|
// AAPCS64: https://developer.arm.com/docs/ihi0055/latest
|
||
|
// iOS64: https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html
|
||
|
//
|
||
|
// In aarch64, r18 (accessed as w18 or x18 in a 64-bit context) is the platform
|
||
|
// register. iOS says user code may not touch it. We found no clear reference
|
||
|
// for Linux. The iOS behavior implies portable assembly cannot use it, and
|
||
|
// aarch64 has many registers. Thus this framework ignores register's existence.
|
||
|
// We test r18 violations in arm-xlate.pl.
|
||
|
#define LOOP_CALLER_STATE_REGISTERS() \
|
||
|
/* Per AAPCS64, section 5.1.2, only the bottom 64 bits of v8-v15 */ \
|
||
|
/* are preserved. These are accessed as dN. */ \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d8) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d9) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d10) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d11) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d12) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d13) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d14) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, d15) \
|
||
|
/* For consistency with dN, use the 64-bit name xN, rather than */ \
|
||
|
/* the generic rN. */ \
|
||
|
CALLER_STATE_REGISTER(uint64_t, x19) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, x20) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, x21) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, x22) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, x23) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, x24) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, x25) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, x26) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, x27) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, x28) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, x29)
|
||
|
|
||
|
#elif defined(OPENSSL_PPC64LE)
|
||
|
|
||
|
// CRReg only compares the CR2-CR4 bits of a CR register.
|
||
|
struct CRReg {
|
||
|
uint32_t masked() const { return value & 0x00fff000; }
|
||
|
bool operator==(CRReg r) const { return masked() == r.masked(); }
|
||
|
bool operator!=(CRReg r) const { return masked() != r.masked(); }
|
||
|
uint32_t value;
|
||
|
};
|
||
|
|
||
|
// References:
|
||
|
// ELFv2: http://openpowerfoundation.org/wp-content/uploads/resources/leabi/leabi-20170510.pdf
|
||
|
//
|
||
|
// Note vector and floating-point registers on POWER have two different names.
|
||
|
// Originally, there were 32 floating-point registers and 32 vector registers,
|
||
|
// labelled f0-f31 and v0-v31 respectively. Later, VSX (Vector Scalar Extension)
|
||
|
// unified them into 64 registers vs0-vs63. f0-f31 map to the lower halves of
|
||
|
// vs0-vs31. v0-v31 map to vs32-vs63. The ABI was defined in terms of pre-VSX
|
||
|
// names, so we use those names here. In particular, f14-f31 are
|
||
|
// callee-saved, but the upper halves of vs14-vs31 are not.
|
||
|
#define LOOP_CALLER_STATE_REGISTERS() \
|
||
|
CALLER_STATE_REGISTER(Reg128, v20) \
|
||
|
CALLER_STATE_REGISTER(Reg128, v21) \
|
||
|
CALLER_STATE_REGISTER(Reg128, v22) \
|
||
|
CALLER_STATE_REGISTER(Reg128, v23) \
|
||
|
CALLER_STATE_REGISTER(Reg128, v24) \
|
||
|
CALLER_STATE_REGISTER(Reg128, v25) \
|
||
|
CALLER_STATE_REGISTER(Reg128, v26) \
|
||
|
CALLER_STATE_REGISTER(Reg128, v27) \
|
||
|
CALLER_STATE_REGISTER(Reg128, v28) \
|
||
|
CALLER_STATE_REGISTER(Reg128, v29) \
|
||
|
CALLER_STATE_REGISTER(Reg128, v30) \
|
||
|
CALLER_STATE_REGISTER(Reg128, v31) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r14) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r15) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r16) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r17) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r18) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r19) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r20) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r21) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r22) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r23) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r24) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r25) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r26) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r27) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r28) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r29) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r30) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, r31) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f14) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f15) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f16) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f17) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f18) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f19) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f20) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f21) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f22) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f23) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f24) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f25) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f26) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f27) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f28) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f29) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f30) \
|
||
|
CALLER_STATE_REGISTER(uint64_t, f31) \
|
||
|
CALLER_STATE_REGISTER(CRReg, cr)
|
||
|
|
||
|
#endif // X86_64 || X86 || ARM || AARCH64 || PPC64LE
|
||
|
|
||
|
// Enable ABI testing if all of the following are true.
|
||
|
//
|
||
|
// - We have CallerState and trampoline support for the architecture.
|
||
|
//
|
||
|
// - Assembly is enabled.
|
||
|
//
|
||
|
// - This is not a shared library build. Assembly functions are not reachable
|
||
|
// from tests in shared library builds.
|
||
|
#if defined(LOOP_CALLER_STATE_REGISTERS) && !defined(OPENSSL_NO_ASM) && \
|
||
|
!defined(BORINGSSL_SHARED_LIBRARY)
|
||
|
#define SUPPORTS_ABI_TEST
|
||
|
|
||
|
// CallerState contains all caller state that the callee is expected to
|
||
|
// preserve.
|
||
|
struct CallerState {
|
||
|
#define CALLER_STATE_REGISTER(type, name) type name;
|
||
|
LOOP_CALLER_STATE_REGISTERS()
|
||
|
#undef CALLER_STATE_REGISTER
|
||
|
};
|
||
|
|
||
|
// RunTrampoline runs |func| on |argv|, recording ABI errors in |out|. It does
|
||
|
// not perform any type-checking. If |unwind| is true and unwind tests have been
|
||
|
// enabled, |func| is single-stepped under an unwind test.
|
||
|
crypto_word_t RunTrampoline(Result *out, crypto_word_t func,
|
||
|
const crypto_word_t *argv, size_t argc,
|
||
|
bool unwind);
|
||
|
|
||
|
template <typename T>
|
||
|
inline crypto_word_t ToWord(T t) {
|
||
|
// ABIs typically pass floats and structs differently from integers and
|
||
|
// pointers. We only need to support the latter.
|
||
|
static_assert(std::is_integral<T>::value || std::is_pointer<T>::value,
|
||
|
"parameter types must be integral or pointer types");
|
||
|
// We only support types which fit in registers.
|
||
|
static_assert(sizeof(T) <= sizeof(crypto_word_t),
|
||
|
"parameter types must be at most word-sized");
|
||
|
|
||
|
// ABIs are complex around arguments that are smaller than native words.
|
||
|
// Parameters passed in memory are sometimes packed and sometimes padded to a
|
||
|
// word. When parameters are padded in memory or passed in a larger register,
|
||
|
// the unused bits may be undefined or sign- or zero-extended.
|
||
|
//
|
||
|
// We could simply cast to |crypto_word_t| everywhere but, on platforms where
|
||
|
// padding is undefined, we perturb the bits to test the function accounts for
|
||
|
// for this.
|
||
|
#if defined(OPENSSL_32_BIT)
|
||
|
// We never pass parameters smaller than int, so require word-sized parameters
|
||
|
// on 32-bit architectures for simplicity.
|
||
|
static_assert(sizeof(T) == 4, "parameter types must be word-sized");
|
||
|
return (crypto_word_t)t;
|
||
|
#elif defined(OPENSSL_PPC64LE)
|
||
|
// ELFv2, section 2.2.2.3 says the parameter save area sign- or zero-extends
|
||
|
// parameters passed in memory. Section 2.2.3 is unclear on how to handle
|
||
|
// register parameters, but section 2.2.2.3 additionally says that the memory
|
||
|
// copy of a parameter is identical to the register one.
|
||
|
return (crypto_word_t)t;
|
||
|
#elif defined(OPENSSL_X86_64) || defined(OPENSSL_AARCH64)
|
||
|
// AAPCS64, section 5.4.2, clauses C.7 and C.14 says any remaining bits in
|
||
|
// aarch are unspecified. iOS64 contradicts this and says the callee extends
|
||
|
// arguments up to 32 bits, and only the upper 32 bits are unspecified.
|
||
|
//
|
||
|
// On x86_64, Win64 leaves all unused bits unspecified. SysV also leaves
|
||
|
// unused bits in stack parameters unspecified, but it behaves like iOS64 for
|
||
|
// register parameters. This was determined via experimentation.
|
||
|
//
|
||
|
// We limit to 32-bit and 64-bit parameters, the subset where the above all
|
||
|
// align, and then test that functions tolerate arbitrary unused bits.
|
||
|
//
|
||
|
// TODO(davidben): Find authoritative citations for x86_64. For x86_64, I
|
||
|
// observed the behavior of Clang, GCC, and MSVC. ABI rules here may be
|
||
|
// inferred from two kinds of experiments:
|
||
|
//
|
||
|
// 1. When passing a value to a small-argument-taking function, does the
|
||
|
// compiler ensure unused bits are cleared, sign-extended, etc.? Tests for
|
||
|
// register parameters are confounded by x86_64's implicit clearing of
|
||
|
// registers' upper halves, but passing some_u64 >> 1 usually clears this.
|
||
|
//
|
||
|
// 2. When compiling a small-argument-taking function, does the compiler make
|
||
|
// assumptions about unused bits of arguments?
|
||
|
//
|
||
|
// MSVC was observed to tolerate and produce arbitrary values for unused bits,
|
||
|
// which is conclusive. GCC and Clang, targeting Linux, were similarly
|
||
|
// conclusive on stack parameters. Clang was also conclusive for register
|
||
|
// parameters. Callers only extended parameters up to 32 bits, and callees
|
||
|
// took advantage of the 32-bit extension. GCC only exhibited the callee
|
||
|
// behavior.
|
||
|
static_assert(sizeof(T) >= 4, "parameters must be at least 32 bits wide");
|
||
|
crypto_word_t ret;
|
||
|
// Filling extra bits with 0xaa will be vastly out of bounds for code
|
||
|
// expecting either sign- or zero-extension. (0xaa is 0b10101010.)
|
||
|
OPENSSL_memset(&ret, 0xaa, sizeof(ret));
|
||
|
OPENSSL_memcpy(&ret, &t, sizeof(t));
|
||
|
return ret;
|
||
|
#else
|
||
|
#error "unknown architecture"
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
// CheckImpl runs |func| on |args|, recording ABI errors in |out|. If |unwind|
|
||
|
// is true and unwind tests have been enabled, |func| is single-stepped under an
|
||
|
// unwind test.
|
||
|
//
|
||
|
// It returns the value as a |crypto_word_t| to work around problems when |R| is
|
||
|
// void. |args| is wrapped in a |DeductionGuard| so |func| determines the
|
||
|
// template arguments. Otherwise, |args| may deduce |Args| incorrectly. For
|
||
|
// instance, if |func| takes const int *, and the caller passes an int *, the
|
||
|
// compiler will complain the deduced types do not match.
|
||
|
template <typename R, typename... Args>
|
||
|
inline crypto_word_t CheckImpl(Result *out, bool unwind, R (*func)(Args...),
|
||
|
typename DeductionGuard<Args>::Type... args) {
|
||
|
// We only support up to 8 arguments, so all arguments on aarch64 and ppc64le
|
||
|
// are passed in registers. This is simpler and avoids the iOS discrepancy
|
||
|
// around packing small arguments on the stack. (See the iOS64 reference.)
|
||
|
static_assert(sizeof...(args) <= 8,
|
||
|
"too many arguments for abi_test_trampoline");
|
||
|
|
||
|
// Allocate one extra entry so MSVC does not complain about zero-size arrays.
|
||
|
crypto_word_t argv[sizeof...(args) + 1] = {
|
||
|
ToWord(args)...,
|
||
|
};
|
||
|
return RunTrampoline(out, reinterpret_cast<crypto_word_t>(func), argv,
|
||
|
sizeof...(args), unwind);
|
||
|
}
|
||
|
#else
|
||
|
// To simplify callers when ABI testing support is unavoidable, provide a backup
|
||
|
// CheckImpl implementation. It must be specialized for void returns because we
|
||
|
// call |func| directly.
|
||
|
template <typename R, typename... Args>
|
||
|
inline typename std::enable_if<!std::is_void<R>::value, crypto_word_t>::type
|
||
|
CheckImpl(Result *out, bool /* unwind */, R (*func)(Args...),
|
||
|
typename DeductionGuard<Args>::Type... args) {
|
||
|
*out = Result();
|
||
|
return func(args...);
|
||
|
}
|
||
|
|
||
|
template <typename... Args>
|
||
|
inline crypto_word_t CheckImpl(Result *out, bool /* unwind */,
|
||
|
void (*func)(Args...),
|
||
|
typename DeductionGuard<Args>::Type... args) {
|
||
|
*out = Result();
|
||
|
func(args...);
|
||
|
return 0;
|
||
|
}
|
||
|
#endif // SUPPORTS_ABI_TEST
|
||
|
|
||
|
// FixVAArgsString takes a string like "f, 1, 2" and returns a string like
|
||
|
// "f(1, 2)".
|
||
|
//
|
||
|
// This is needed because the |CHECK_ABI| macro below cannot be defined as
|
||
|
// CHECK_ABI(func, ...). The C specification requires that variadic macros bind
|
||
|
// at least one variadic argument. Clang, GCC, and MSVC all ignore this, but
|
||
|
// there are issues with trailing commas and different behaviors across
|
||
|
// compilers.
|
||
|
std::string FixVAArgsString(const char *str);
|
||
|
|
||
|
// CheckGTest behaves like |CheckImpl|, but it returns the correct type and
|
||
|
// raises GTest assertions on failure. If |unwind| is true and unwind tests are
|
||
|
// enabled, |func| is single-stepped under an unwind test.
|
||
|
template <typename R, typename... Args>
|
||
|
inline R CheckGTest(const char *va_args_str, const char *file, int line,
|
||
|
bool unwind, R (*func)(Args...),
|
||
|
typename DeductionGuard<Args>::Type... args) {
|
||
|
Result result;
|
||
|
crypto_word_t ret = CheckImpl(&result, unwind, func, args...);
|
||
|
if (!result.ok()) {
|
||
|
testing::Message msg;
|
||
|
msg << "ABI failures in " << FixVAArgsString(va_args_str) << ":\n";
|
||
|
for (const auto &error : result.errors) {
|
||
|
msg << " " << error << "\n";
|
||
|
}
|
||
|
ADD_FAILURE_AT(file, line) << msg;
|
||
|
}
|
||
|
return (R)ret;
|
||
|
}
|
||
|
|
||
|
} // namespace internal
|
||
|
|
||
|
// Check runs |func| on |args| and returns the result. If ABI-testing is
|
||
|
// supported in this build configuration, it writes any ABI failures to |out|.
|
||
|
// Otherwise, it runs the function transparently.
|
||
|
template <typename R, typename... Args>
|
||
|
inline R Check(Result *out, R (*func)(Args...),
|
||
|
typename internal::DeductionGuard<Args>::Type... args) {
|
||
|
return (R)internal::CheckImpl(out, false, func, args...);
|
||
|
}
|
||
|
|
||
|
// EnableUnwindTests enables unwind tests, if supported. If not supported, it
|
||
|
// does nothing.
|
||
|
void EnableUnwindTests();
|
||
|
|
||
|
// UnwindTestsEnabled returns true if unwind tests are enabled and false
|
||
|
// otherwise.
|
||
|
bool UnwindTestsEnabled();
|
||
|
|
||
|
} // namespace abi_test
|
||
|
|
||
|
// CHECK_ABI calls the first argument on the remaining arguments and returns the
|
||
|
// result. If ABI-testing is supported in this build configuration, it adds a
|
||
|
// non-fatal GTest failure if the call did not satisfy ABI requirements.
|
||
|
//
|
||
|
// |CHECK_ABI| does return the value and thus may replace any function call,
|
||
|
// provided it takes only simple parameters. However, it is recommended to test
|
||
|
// ABI separately from functional tests of assembly. Fully instrumenting a
|
||
|
// function for ABI checking requires single-stepping the function, which is
|
||
|
// inefficient.
|
||
|
//
|
||
|
// Functional testing requires coverage of input values, while ABI testing only
|
||
|
// requires branch coverage. Most of our assembly is constant-time, so usually
|
||
|
// only a few instrumented calls are necessary.
|
||
|
//
|
||
|
// TODO(https://crbug.com/boringssl/259): Most of Windows assembly currently
|
||
|
// fails SEH testing. For now, |CHECK_ABI| behaves like |CHECK_ABI_NO_UNWIND|
|
||
|
// on Windows. Functions which work with unwind testing on Windows should use
|
||
|
// |CHECK_ABI_SEH|.
|
||
|
#if defined(OPENSSL_WINDOWS)
|
||
|
#define CHECK_ABI(...) CHECK_ABI_NO_UNWIND(__VA_ARGS__)
|
||
|
#else
|
||
|
#define CHECK_ABI(...) CHECK_ABI_SEH(__VA_ARGS__)
|
||
|
#endif
|
||
|
|
||
|
// CHECK_ABI_SEH behaves like |CHECK_ABI| but enables unwind testing on Windows.
|
||
|
#define CHECK_ABI_SEH(...) \
|
||
|
abi_test::internal::CheckGTest(#__VA_ARGS__, __FILE__, __LINE__, true, \
|
||
|
__VA_ARGS__)
|
||
|
|
||
|
// CHECK_ABI_NO_UNWIND behaves like |CHECK_ABI| but disables unwind testing.
|
||
|
#define CHECK_ABI_NO_UNWIND(...) \
|
||
|
abi_test::internal::CheckGTest(#__VA_ARGS__, __FILE__, __LINE__, false, \
|
||
|
__VA_ARGS__)
|
||
|
|
||
|
|
||
|
// Internal functions.
|
||
|
|
||
|
#if defined(SUPPORTS_ABI_TEST)
|
||
|
struct Uncallable {
|
||
|
Uncallable() = delete;
|
||
|
};
|
||
|
|
||
|
extern "C" {
|
||
|
|
||
|
// 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|. If |unwind| is non-zero, this function triggers unwind
|
||
|
// instrumentation.
|
||
|
//
|
||
|
// We give |func| type |crypto_word_t| to avoid tripping MSVC's warning 4191.
|
||
|
crypto_word_t abi_test_trampoline(crypto_word_t func,
|
||
|
abi_test::internal::CallerState *state,
|
||
|
const crypto_word_t *argv, size_t argc,
|
||
|
crypto_word_t unwind);
|
||
|
|
||
|
#if defined(OPENSSL_X86_64)
|
||
|
// abi_test_unwind_start points at the instruction that starts unwind testing in
|
||
|
// |abi_test_trampoline|. This is the value of the instruction pointer at the
|
||
|
// first |SIGTRAP| during unwind testing.
|
||
|
//
|
||
|
// This symbol is not a function and should not be called.
|
||
|
void abi_test_unwind_start(Uncallable);
|
||
|
|
||
|
// abi_test_unwind_return points at the instruction immediately after the call in
|
||
|
// |abi_test_trampoline|. When unwinding the function under test, this is the
|
||
|
// expected address in the |abi_test_trampoline| frame. After this address, the
|
||
|
// unwind tester should ignore |SIGTRAP| until |abi_test_unwind_stop|.
|
||
|
//
|
||
|
// This symbol is not a function and should not be called.
|
||
|
void abi_test_unwind_return(Uncallable);
|
||
|
|
||
|
// abi_test_unwind_stop is the value of the instruction pointer at the final
|
||
|
// |SIGTRAP| during unwind testing.
|
||
|
//
|
||
|
// This symbol is not a function and should not be called.
|
||
|
void abi_test_unwind_stop(Uncallable);
|
||
|
|
||
|
// abi_test_bad_unwind_wrong_register preserves the ABI, but annotates the wrong
|
||
|
// register in unwind metadata.
|
||
|
void abi_test_bad_unwind_wrong_register(void);
|
||
|
|
||
|
// abi_test_bad_unwind_temporary preserves the ABI, but temporarily corrupts the
|
||
|
// storage space for a saved register, breaking unwind.
|
||
|
void abi_test_bad_unwind_temporary(void);
|
||
|
|
||
|
#if defined(OPENSSL_WINDOWS)
|
||
|
// abi_test_bad_unwind_epilog preserves the ABI, and correctly annotates the
|
||
|
// prolog, but the epilog does not match Win64's rules, breaking unwind during
|
||
|
// the epilog.
|
||
|
void abi_test_bad_unwind_epilog(void);
|
||
|
#endif
|
||
|
#endif // OPENSSL_X86_64
|
||
|
|
||
|
#if defined(OPENSSL_X86_64) || defined(OPENSSL_X86)
|
||
|
// abi_test_get_and_clear_direction_flag clears the direction flag. If the flag
|
||
|
// was previously set, it returns one. Otherwise, it returns zero.
|
||
|
int abi_test_get_and_clear_direction_flag(void);
|
||
|
|
||
|
// abi_test_set_direction_flag sets the direction flag. This does not conform to
|
||
|
// ABI requirements and must only be called within a |CHECK_ABI| guard to avoid
|
||
|
// errors later in the program.
|
||
|
int abi_test_set_direction_flag(void);
|
||
|
#endif // OPENSSL_X86_64 || OPENSSL_X86
|
||
|
|
||
|
} // extern "C"
|
||
|
#endif // SUPPORTS_ABI_TEST
|
||
|
|
||
|
|
||
|
#endif // OPENSSL_HEADER_ABI_TEST_H
|