boringssl/crypto/test/abi_test.h

305 lines
12 KiB
C
Raw Normal View History

Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
/* 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.
//
// TODO(davidben): Add support for other architectures.
#if defined(OPENSSL_X86_64)
#if defined(OPENSSL_WINDOWS)
// See https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions?view=vs-2017#register-usage
#define LOOP_CALLER_STATE_REGISTERS() \
CALLER_STATE_REGISTER(uint64_t, rbx) \
CALLER_STATE_REGISTER(uint64_t, rbp) \
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
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
// See https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf
#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
#endif // X86_64 && SUPPORTS_ABI_TEST
// 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)
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
#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
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
// not perform any type-checking. If |unwind| is true and unwind tests have been
// enabled, |func| is single-stepped under an unwind test.
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
crypto_word_t RunTrampoline(Result *out, crypto_word_t func,
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
const crypto_word_t *argv, size_t argc,
bool unwind);
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
// 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.
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
//
// 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>
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
inline crypto_word_t CheckImpl(Result *out, bool unwind, R (*func)(Args...),
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
typename DeductionGuard<Args>::Type... args) {
static_assert(sizeof...(args) <= 10,
"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] = {
(crypto_word_t)args...,
};
return RunTrampoline(out, reinterpret_cast<crypto_word_t>(func), argv,
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
sizeof...(args), unwind);
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
}
#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
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
CheckImpl(Result *out, bool /* unwind */, R (*func)(Args...),
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
typename DeductionGuard<Args>::Type... args) {
*out = Result();
return func(args...);
}
template <typename... Args>
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
inline crypto_word_t CheckImpl(Result *out, bool /* unwind */,
void (*func)(Args...),
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
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
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
// raises GTest assertions on failure. If |unwind| is true and unwind tests are
// enabled, |func| is single-stepped under an unwind test.
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
template <typename R, typename... Args>
inline R CheckGTest(const char *va_args_str, const char *file, int line,
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
bool unwind, R (*func)(Args...),
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
typename DeductionGuard<Args>::Type... args) {
Result result;
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
crypto_word_t ret = CheckImpl(&result, unwind, func, args...);
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
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) {
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
return (R)internal::CheckImpl(out, false, func, args...);
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
}
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
// 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();
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
} // 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
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
// 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 necessray.
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
#define CHECK_ABI(...) \
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__)
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
// Internal functions.
#if defined(SUPPORTS_ABI_TEST)
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
struct Uncallable {
Uncallable() = delete;
};
extern "C" {
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
// abi_test_trampoline loads callee-saved registers from |state|, calls |func|
// with |argv|, then saves the callee-saved registers into |state|. It returns
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
// 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);
// 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 CFI 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_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
Add a CFI tester to CHECK_ABI. This uses the x86 trap flag and libunwind to test CFI works at each instruction. For now, it just uses the system one out of pkg-config and disables unwind tests if unavailable. We'll probably want to stick a copy into //third_party and perhaps try the LLVM one later. This tester caught two bugs in P-256 CFI annotations already: I47b5f9798b3bcee1748e537b21c173d312a14b42 and I9f576d868850312d6c14d1386f8fbfa85021b347 An earlier design used PTRACE_SINGLESTEP with libunwind's remote unwinding features. ptrace is a mess around stop signals (see group-stop discussion in ptrace(2)) and this is 10x faster, so I went with it. The question of which is more future-proof is complex: - There are two libunwinds with the same API, https://www.nongnu.org/libunwind/ and LLVM's. This currently uses the system nongnu.org for convenience. In future, LLVM's should be easier to bundle (less complex build) and appears to even support Windows, but I haven't tested this. Moreover, setting the trap flag keeps the test single-process, which is less complex on Windows. That suggests the trap flag design and switching to LLVM later. However... - Not all architectures have a trap flag settable by userspace. As far as I can tell, ARMv8's PSTATE.SS can only be set from the kernel. If we stick with nongnu.org libunwind, we can use PTRACE_SINGLESTEP and remote unwinding. Or we implement it for LLVM. Another thought is for the ptracer to bounce SIGTRAP back into the process, to share the local unwinding code. - ARMv7 has no trap flag at all and PTRACE_SINGLESTEP fails. Debuggers single-step by injecting breakpoints instead. However, ARMv8's trap flag seems to work in both AArch32 and AArch64 modes, so we may be able to condition it on a 64-bit kernel. Sadly, neither strategy works with Intel SDE. Adding flags to cpucap vectors as we do with ARM would help, but it would not emulate CPUs newer than the host CPU. For now, I've just had SDE tests disable these. Annoyingly, CMake does not allow object libraries to have dependencies, so make test_support a proper static library. Rename the target to test_support_lib to avoid https://gitlab.kitware.com/cmake/cmake/issues/17785 Update-Note: This adds a new optional test dependency, but it's disabled by default (define BORINGSSL_HAVE_LIBUNWIND), so consumers do not need to do anything. We'll probably want to adjust this in the future. Bug: 181 Change-Id: I817263d7907aff0904a9cee83f8b26747262cc0c Reviewed-on: https://boringssl-review.googlesource.com/c/33966 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
2018-12-21 23:58:36 +00:00
} // extern "C"
Add an ABI testing framework. Dear reader, I must apologize in advance. This CL contains the following: - A new 256-line perlasm file with non-trivial perl bits and a dual-ABI variadic function caller. - C preprocessor gymnastics, with variadic macros and fun facts about __VA_ARGS__'s behavior on empty argument lists. - C++ template gymnastics, including variadic arguments, template specialization, std::enable_if, and machinery to control template argument deduction. Enjoy. This tests that our assembly functions correctly honor platform ABI conventions. Right now this only tests callee-saved registers, but it should be extendable to SEH/CFI unwind testing with single-step debugging APIs. Register-checking does not involve anything funny and should be compatible with SDE. (The future unwind testing is unlikely to be compatible.) This CL adds support for x86_64 SysV and Win64 ABIs. ARM, AArch64, and x86 can be added in the future. The testing is injected in two places. First, all the assembly tests in p256-x86_64-test.cc are now instrumented. This is the intended workflow and should capture all registers. However, we currently do not unit-test our assembly much directly. We should do that as follow-up work[0] but, in the meantime, I've also wrapped all of the GTest main function in an ABI test. This is imperfect as ABI failures may be masked by other stack frames, but it costs nothing[1] and is pretty reliable at catching Win64 xmm register failures. [0] An alternate strategy would be, in debug builds, unconditionally instrument every assembly call in libcrypto. But the CHECK_ABI macro would be difficult to replicate in pure C, and unwind testing may be too invasive for this. Still, something to consider when we C++ libcrypto. [1] When single-stepped unwind testing exists, it won't cost nothing. The gtest_main.cc call will turn unwind testing off. Change-Id: I6643b26445891fd46abfacac52bc024024c8d7f6 Reviewed-on: https://boringssl-review.googlesource.com/c/33764 Reviewed-by: Adam Langley <agl@google.com> Reviewed-by: Adam Langley <alangley@gmail.com> Commit-Queue: David Benjamin <davidben@google.com>
2018-12-16 00:58:43 +00:00
#endif // SUPPORTS_ABI_TEST
#endif // OPENSSL_HEADER_ABI_TEST_H