You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
Test and fix an ABI issue with small parameters. Calling conventions must specify how to handle arguments smaller than a machine word. Should the caller pad them up to a machine word size with predictable values (zero/sign-extended), or should the callee tolerate an arbitrary bit pattern? Annoyingly, I found no text in either SysV or Win64 ABI documentation describing any of this and resorted to experiment. The short answer is that callees must tolerate an arbitrary bit pattern on x86_64, which means we must test this. See the comment in abi_test::internal::ToWord for the long answer. CHECK_ABI now, if the type of the parameter is smaller than crypto_word_t, fills the remaining bytes with 0xaa. This is so the number is out of bounds for code expecting either zero or sign extension. (Not that crypto assembly has any business seeing negative numbers.) Doing so reveals a bug in ecp_nistz256_ord_sqr_mont. The rep parameter is typed int, but the code expected uint64_t. In practice, the compiler will always compile this correctly because: - On both Win64 and SysV, rep is a register parameter. - The rep parameter is always a constant, so the compiler has no reason to leave garbage in the upper half. However, I was indeed able to get a bug out of GCC via: uint64_t foo = (1ull << 63) | 2; // Some global the compiler can't // prove constant. ecp_nistz256_ord_sqr_mont(res, a, foo >> 1); Were ecp_nistz256_ord_sqr_mont a true int-taking function, this would act like ecp_nistz256_ord_sqr_mont(res, a, 1). Instead, it hung. Fix this by having it take a full-width word. This mess has several consequences: - ABI testing now ideally needs a functional testing component to fully cover this case. A bad input might merely produce the wrong answer. Still, this is fairly effective as it will cause most code to either segfault or loop forever. (Not the enc parameter to AES however...) - We cannot freely change the type of assembly function prototypes. If the prototype says int or unsigned, it must be ignoring the upper half and thus "fixing" it to size_t cannot have handled the full range. (Unless it was simply wrong of the parameter is already bounded.) If the prototype says size_t, switching to int or unsigned will hit this type of bug. The former is a safer failure mode though. - The simplest path out of this mess: new assembly code should *only* ever take word-sized parameters. This is not a tall order as the bad parameters are usually ints that should have been size_t. Calling conventions are hard. Change-Id: If8254aff8953844679fbce4bd3e345e5e2fa5213 Reviewed-on: https://boringssl-review.googlesource.com/c/34627 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
5 年之前
Test and fix an ABI issue with small parameters. Calling conventions must specify how to handle arguments smaller than a machine word. Should the caller pad them up to a machine word size with predictable values (zero/sign-extended), or should the callee tolerate an arbitrary bit pattern? Annoyingly, I found no text in either SysV or Win64 ABI documentation describing any of this and resorted to experiment. The short answer is that callees must tolerate an arbitrary bit pattern on x86_64, which means we must test this. See the comment in abi_test::internal::ToWord for the long answer. CHECK_ABI now, if the type of the parameter is smaller than crypto_word_t, fills the remaining bytes with 0xaa. This is so the number is out of bounds for code expecting either zero or sign extension. (Not that crypto assembly has any business seeing negative numbers.) Doing so reveals a bug in ecp_nistz256_ord_sqr_mont. The rep parameter is typed int, but the code expected uint64_t. In practice, the compiler will always compile this correctly because: - On both Win64 and SysV, rep is a register parameter. - The rep parameter is always a constant, so the compiler has no reason to leave garbage in the upper half. However, I was indeed able to get a bug out of GCC via: uint64_t foo = (1ull << 63) | 2; // Some global the compiler can't // prove constant. ecp_nistz256_ord_sqr_mont(res, a, foo >> 1); Were ecp_nistz256_ord_sqr_mont a true int-taking function, this would act like ecp_nistz256_ord_sqr_mont(res, a, 1). Instead, it hung. Fix this by having it take a full-width word. This mess has several consequences: - ABI testing now ideally needs a functional testing component to fully cover this case. A bad input might merely produce the wrong answer. Still, this is fairly effective as it will cause most code to either segfault or loop forever. (Not the enc parameter to AES however...) - We cannot freely change the type of assembly function prototypes. If the prototype says int or unsigned, it must be ignoring the upper half and thus "fixing" it to size_t cannot have handled the full range. (Unless it was simply wrong of the parameter is already bounded.) If the prototype says size_t, switching to int or unsigned will hit this type of bug. The former is a safer failure mode though. - The simplest path out of this mess: new assembly code should *only* ever take word-sized parameters. This is not a tall order as the bad parameters are usually ints that should have been size_t. Calling conventions are hard. Change-Id: If8254aff8953844679fbce4bd3e345e5e2fa5213 Reviewed-on: https://boringssl-review.googlesource.com/c/34627 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
5 年之前
Test and fix an ABI issue with small parameters. Calling conventions must specify how to handle arguments smaller than a machine word. Should the caller pad them up to a machine word size with predictable values (zero/sign-extended), or should the callee tolerate an arbitrary bit pattern? Annoyingly, I found no text in either SysV or Win64 ABI documentation describing any of this and resorted to experiment. The short answer is that callees must tolerate an arbitrary bit pattern on x86_64, which means we must test this. See the comment in abi_test::internal::ToWord for the long answer. CHECK_ABI now, if the type of the parameter is smaller than crypto_word_t, fills the remaining bytes with 0xaa. This is so the number is out of bounds for code expecting either zero or sign extension. (Not that crypto assembly has any business seeing negative numbers.) Doing so reveals a bug in ecp_nistz256_ord_sqr_mont. The rep parameter is typed int, but the code expected uint64_t. In practice, the compiler will always compile this correctly because: - On both Win64 and SysV, rep is a register parameter. - The rep parameter is always a constant, so the compiler has no reason to leave garbage in the upper half. However, I was indeed able to get a bug out of GCC via: uint64_t foo = (1ull << 63) | 2; // Some global the compiler can't // prove constant. ecp_nistz256_ord_sqr_mont(res, a, foo >> 1); Were ecp_nistz256_ord_sqr_mont a true int-taking function, this would act like ecp_nistz256_ord_sqr_mont(res, a, 1). Instead, it hung. Fix this by having it take a full-width word. This mess has several consequences: - ABI testing now ideally needs a functional testing component to fully cover this case. A bad input might merely produce the wrong answer. Still, this is fairly effective as it will cause most code to either segfault or loop forever. (Not the enc parameter to AES however...) - We cannot freely change the type of assembly function prototypes. If the prototype says int or unsigned, it must be ignoring the upper half and thus "fixing" it to size_t cannot have handled the full range. (Unless it was simply wrong of the parameter is already bounded.) If the prototype says size_t, switching to int or unsigned will hit this type of bug. The former is a safer failure mode though. - The simplest path out of this mess: new assembly code should *only* ever take word-sized parameters. This is not a tall order as the bad parameters are usually ints that should have been size_t. Calling conventions are hard. Change-Id: If8254aff8953844679fbce4bd3e345e5e2fa5213 Reviewed-on: https://boringssl-review.googlesource.com/c/34627 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
5 年之前
Test and fix an ABI issue with small parameters. Calling conventions must specify how to handle arguments smaller than a machine word. Should the caller pad them up to a machine word size with predictable values (zero/sign-extended), or should the callee tolerate an arbitrary bit pattern? Annoyingly, I found no text in either SysV or Win64 ABI documentation describing any of this and resorted to experiment. The short answer is that callees must tolerate an arbitrary bit pattern on x86_64, which means we must test this. See the comment in abi_test::internal::ToWord for the long answer. CHECK_ABI now, if the type of the parameter is smaller than crypto_word_t, fills the remaining bytes with 0xaa. This is so the number is out of bounds for code expecting either zero or sign extension. (Not that crypto assembly has any business seeing negative numbers.) Doing so reveals a bug in ecp_nistz256_ord_sqr_mont. The rep parameter is typed int, but the code expected uint64_t. In practice, the compiler will always compile this correctly because: - On both Win64 and SysV, rep is a register parameter. - The rep parameter is always a constant, so the compiler has no reason to leave garbage in the upper half. However, I was indeed able to get a bug out of GCC via: uint64_t foo = (1ull << 63) | 2; // Some global the compiler can't // prove constant. ecp_nistz256_ord_sqr_mont(res, a, foo >> 1); Were ecp_nistz256_ord_sqr_mont a true int-taking function, this would act like ecp_nistz256_ord_sqr_mont(res, a, 1). Instead, it hung. Fix this by having it take a full-width word. This mess has several consequences: - ABI testing now ideally needs a functional testing component to fully cover this case. A bad input might merely produce the wrong answer. Still, this is fairly effective as it will cause most code to either segfault or loop forever. (Not the enc parameter to AES however...) - We cannot freely change the type of assembly function prototypes. If the prototype says int or unsigned, it must be ignoring the upper half and thus "fixing" it to size_t cannot have handled the full range. (Unless it was simply wrong of the parameter is already bounded.) If the prototype says size_t, switching to int or unsigned will hit this type of bug. The former is a safer failure mode though. - The simplest path out of this mess: new assembly code should *only* ever take word-sized parameters. This is not a tall order as the bad parameters are usually ints that should have been size_t. Calling conventions are hard. Change-Id: If8254aff8953844679fbce4bd3e345e5e2fa5213 Reviewed-on: https://boringssl-review.googlesource.com/c/34627 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
5 年之前
Test and fix an ABI issue with small parameters. Calling conventions must specify how to handle arguments smaller than a machine word. Should the caller pad them up to a machine word size with predictable values (zero/sign-extended), or should the callee tolerate an arbitrary bit pattern? Annoyingly, I found no text in either SysV or Win64 ABI documentation describing any of this and resorted to experiment. The short answer is that callees must tolerate an arbitrary bit pattern on x86_64, which means we must test this. See the comment in abi_test::internal::ToWord for the long answer. CHECK_ABI now, if the type of the parameter is smaller than crypto_word_t, fills the remaining bytes with 0xaa. This is so the number is out of bounds for code expecting either zero or sign extension. (Not that crypto assembly has any business seeing negative numbers.) Doing so reveals a bug in ecp_nistz256_ord_sqr_mont. The rep parameter is typed int, but the code expected uint64_t. In practice, the compiler will always compile this correctly because: - On both Win64 and SysV, rep is a register parameter. - The rep parameter is always a constant, so the compiler has no reason to leave garbage in the upper half. However, I was indeed able to get a bug out of GCC via: uint64_t foo = (1ull << 63) | 2; // Some global the compiler can't // prove constant. ecp_nistz256_ord_sqr_mont(res, a, foo >> 1); Were ecp_nistz256_ord_sqr_mont a true int-taking function, this would act like ecp_nistz256_ord_sqr_mont(res, a, 1). Instead, it hung. Fix this by having it take a full-width word. This mess has several consequences: - ABI testing now ideally needs a functional testing component to fully cover this case. A bad input might merely produce the wrong answer. Still, this is fairly effective as it will cause most code to either segfault or loop forever. (Not the enc parameter to AES however...) - We cannot freely change the type of assembly function prototypes. If the prototype says int or unsigned, it must be ignoring the upper half and thus "fixing" it to size_t cannot have handled the full range. (Unless it was simply wrong of the parameter is already bounded.) If the prototype says size_t, switching to int or unsigned will hit this type of bug. The former is a safer failure mode though. - The simplest path out of this mess: new assembly code should *only* ever take word-sized parameters. This is not a tall order as the bad parameters are usually ints that should have been size_t. Calling conventions are hard. Change-Id: If8254aff8953844679fbce4bd3e345e5e2fa5213 Reviewed-on: https://boringssl-review.googlesource.com/c/34627 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
5 年之前
Test and fix an ABI issue with small parameters. Calling conventions must specify how to handle arguments smaller than a machine word. Should the caller pad them up to a machine word size with predictable values (zero/sign-extended), or should the callee tolerate an arbitrary bit pattern? Annoyingly, I found no text in either SysV or Win64 ABI documentation describing any of this and resorted to experiment. The short answer is that callees must tolerate an arbitrary bit pattern on x86_64, which means we must test this. See the comment in abi_test::internal::ToWord for the long answer. CHECK_ABI now, if the type of the parameter is smaller than crypto_word_t, fills the remaining bytes with 0xaa. This is so the number is out of bounds for code expecting either zero or sign extension. (Not that crypto assembly has any business seeing negative numbers.) Doing so reveals a bug in ecp_nistz256_ord_sqr_mont. The rep parameter is typed int, but the code expected uint64_t. In practice, the compiler will always compile this correctly because: - On both Win64 and SysV, rep is a register parameter. - The rep parameter is always a constant, so the compiler has no reason to leave garbage in the upper half. However, I was indeed able to get a bug out of GCC via: uint64_t foo = (1ull << 63) | 2; // Some global the compiler can't // prove constant. ecp_nistz256_ord_sqr_mont(res, a, foo >> 1); Were ecp_nistz256_ord_sqr_mont a true int-taking function, this would act like ecp_nistz256_ord_sqr_mont(res, a, 1). Instead, it hung. Fix this by having it take a full-width word. This mess has several consequences: - ABI testing now ideally needs a functional testing component to fully cover this case. A bad input might merely produce the wrong answer. Still, this is fairly effective as it will cause most code to either segfault or loop forever. (Not the enc parameter to AES however...) - We cannot freely change the type of assembly function prototypes. If the prototype says int or unsigned, it must be ignoring the upper half and thus "fixing" it to size_t cannot have handled the full range. (Unless it was simply wrong of the parameter is already bounded.) If the prototype says size_t, switching to int or unsigned will hit this type of bug. The former is a safer failure mode though. - The simplest path out of this mess: new assembly code should *only* ever take word-sized parameters. This is not a tall order as the bad parameters are usually ints that should have been size_t. Calling conventions are hard. Change-Id: If8254aff8953844679fbce4bd3e345e5e2fa5213 Reviewed-on: https://boringssl-review.googlesource.com/c/34627 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
5 年之前
Test and fix an ABI issue with small parameters. Calling conventions must specify how to handle arguments smaller than a machine word. Should the caller pad them up to a machine word size with predictable values (zero/sign-extended), or should the callee tolerate an arbitrary bit pattern? Annoyingly, I found no text in either SysV or Win64 ABI documentation describing any of this and resorted to experiment. The short answer is that callees must tolerate an arbitrary bit pattern on x86_64, which means we must test this. See the comment in abi_test::internal::ToWord for the long answer. CHECK_ABI now, if the type of the parameter is smaller than crypto_word_t, fills the remaining bytes with 0xaa. This is so the number is out of bounds for code expecting either zero or sign extension. (Not that crypto assembly has any business seeing negative numbers.) Doing so reveals a bug in ecp_nistz256_ord_sqr_mont. The rep parameter is typed int, but the code expected uint64_t. In practice, the compiler will always compile this correctly because: - On both Win64 and SysV, rep is a register parameter. - The rep parameter is always a constant, so the compiler has no reason to leave garbage in the upper half. However, I was indeed able to get a bug out of GCC via: uint64_t foo = (1ull << 63) | 2; // Some global the compiler can't // prove constant. ecp_nistz256_ord_sqr_mont(res, a, foo >> 1); Were ecp_nistz256_ord_sqr_mont a true int-taking function, this would act like ecp_nistz256_ord_sqr_mont(res, a, 1). Instead, it hung. Fix this by having it take a full-width word. This mess has several consequences: - ABI testing now ideally needs a functional testing component to fully cover this case. A bad input might merely produce the wrong answer. Still, this is fairly effective as it will cause most code to either segfault or loop forever. (Not the enc parameter to AES however...) - We cannot freely change the type of assembly function prototypes. If the prototype says int or unsigned, it must be ignoring the upper half and thus "fixing" it to size_t cannot have handled the full range. (Unless it was simply wrong of the parameter is already bounded.) If the prototype says size_t, switching to int or unsigned will hit this type of bug. The former is a safer failure mode though. - The simplest path out of this mess: new assembly code should *only* ever take word-sized parameters. This is not a tall order as the bad parameters are usually ints that should have been size_t. Calling conventions are hard. Change-Id: If8254aff8953844679fbce4bd3e345e5e2fa5213 Reviewed-on: https://boringssl-review.googlesource.com/c/34627 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
5 年之前
Test and fix an ABI issue with small parameters. Calling conventions must specify how to handle arguments smaller than a machine word. Should the caller pad them up to a machine word size with predictable values (zero/sign-extended), or should the callee tolerate an arbitrary bit pattern? Annoyingly, I found no text in either SysV or Win64 ABI documentation describing any of this and resorted to experiment. The short answer is that callees must tolerate an arbitrary bit pattern on x86_64, which means we must test this. See the comment in abi_test::internal::ToWord for the long answer. CHECK_ABI now, if the type of the parameter is smaller than crypto_word_t, fills the remaining bytes with 0xaa. This is so the number is out of bounds for code expecting either zero or sign extension. (Not that crypto assembly has any business seeing negative numbers.) Doing so reveals a bug in ecp_nistz256_ord_sqr_mont. The rep parameter is typed int, but the code expected uint64_t. In practice, the compiler will always compile this correctly because: - On both Win64 and SysV, rep is a register parameter. - The rep parameter is always a constant, so the compiler has no reason to leave garbage in the upper half. However, I was indeed able to get a bug out of GCC via: uint64_t foo = (1ull << 63) | 2; // Some global the compiler can't // prove constant. ecp_nistz256_ord_sqr_mont(res, a, foo >> 1); Were ecp_nistz256_ord_sqr_mont a true int-taking function, this would act like ecp_nistz256_ord_sqr_mont(res, a, 1). Instead, it hung. Fix this by having it take a full-width word. This mess has several consequences: - ABI testing now ideally needs a functional testing component to fully cover this case. A bad input might merely produce the wrong answer. Still, this is fairly effective as it will cause most code to either segfault or loop forever. (Not the enc parameter to AES however...) - We cannot freely change the type of assembly function prototypes. If the prototype says int or unsigned, it must be ignoring the upper half and thus "fixing" it to size_t cannot have handled the full range. (Unless it was simply wrong of the parameter is already bounded.) If the prototype says size_t, switching to int or unsigned will hit this type of bug. The former is a safer failure mode though. - The simplest path out of this mess: new assembly code should *only* ever take word-sized parameters. This is not a tall order as the bad parameters are usually ints that should have been size_t. Calling conventions are hard. Change-Id: If8254aff8953844679fbce4bd3e345e5e2fa5213 Reviewed-on: https://boringssl-review.googlesource.com/c/34627 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
Test and fix an ABI issue with small parameters. Calling conventions must specify how to handle arguments smaller than a machine word. Should the caller pad them up to a machine word size with predictable values (zero/sign-extended), or should the callee tolerate an arbitrary bit pattern? Annoyingly, I found no text in either SysV or Win64 ABI documentation describing any of this and resorted to experiment. The short answer is that callees must tolerate an arbitrary bit pattern on x86_64, which means we must test this. See the comment in abi_test::internal::ToWord for the long answer. CHECK_ABI now, if the type of the parameter is smaller than crypto_word_t, fills the remaining bytes with 0xaa. This is so the number is out of bounds for code expecting either zero or sign extension. (Not that crypto assembly has any business seeing negative numbers.) Doing so reveals a bug in ecp_nistz256_ord_sqr_mont. The rep parameter is typed int, but the code expected uint64_t. In practice, the compiler will always compile this correctly because: - On both Win64 and SysV, rep is a register parameter. - The rep parameter is always a constant, so the compiler has no reason to leave garbage in the upper half. However, I was indeed able to get a bug out of GCC via: uint64_t foo = (1ull << 63) | 2; // Some global the compiler can't // prove constant. ecp_nistz256_ord_sqr_mont(res, a, foo >> 1); Were ecp_nistz256_ord_sqr_mont a true int-taking function, this would act like ecp_nistz256_ord_sqr_mont(res, a, 1). Instead, it hung. Fix this by having it take a full-width word. This mess has several consequences: - ABI testing now ideally needs a functional testing component to fully cover this case. A bad input might merely produce the wrong answer. Still, this is fairly effective as it will cause most code to either segfault or loop forever. (Not the enc parameter to AES however...) - We cannot freely change the type of assembly function prototypes. If the prototype says int or unsigned, it must be ignoring the upper half and thus "fixing" it to size_t cannot have handled the full range. (Unless it was simply wrong of the parameter is already bounded.) If the prototype says size_t, switching to int or unsigned will hit this type of bug. The former is a safer failure mode though. - The simplest path out of this mess: new assembly code should *only* ever take word-sized parameters. This is not a tall order as the bad parameters are usually ints that should have been size_t. Calling conventions are hard. Change-Id: If8254aff8953844679fbce4bd3e345e5e2fa5213 Reviewed-on: https://boringssl-review.googlesource.com/c/34627 Commit-Queue: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
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>
5 年之前
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477
  1. /* Copyright (c) 2018, Google Inc.
  2. *
  3. * Permission to use, copy, modify, and/or distribute this software for any
  4. * purpose with or without fee is hereby granted, provided that the above
  5. * copyright notice and this permission notice appear in all copies.
  6. *
  7. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. #ifndef OPENSSL_HEADER_ABI_TEST_H
  15. #define OPENSSL_HEADER_ABI_TEST_H
  16. #include <gtest/gtest.h>
  17. #include <string>
  18. #include <type_traits>
  19. #include <vector>
  20. #include <openssl/base.h>
  21. #include "../internal.h"
  22. // abi_test provides routines for verifying that functions satisfy platform ABI
  23. // requirements.
  24. namespace abi_test {
  25. // Result stores the result of an ABI test.
  26. struct Result {
  27. bool ok() const { return errors.empty(); }
  28. std::vector<std::string> errors;
  29. };
  30. namespace internal {
  31. // DeductionGuard wraps |T| in a template, so that template argument deduction
  32. // does not apply to it. This may be used to force C++ to deduce template
  33. // arguments from another parameter.
  34. template <typename T>
  35. struct DeductionGuard {
  36. using Type = T;
  37. };
  38. // Reg128 contains storage space for a 128-bit register.
  39. struct alignas(16) Reg128 {
  40. bool operator==(const Reg128 &x) const { return x.lo == lo && x.hi == hi; }
  41. bool operator!=(const Reg128 &x) const { return !((*this) == x); }
  42. uint64_t lo, hi;
  43. };
  44. // LOOP_CALLER_STATE_REGISTERS is a macro that iterates over all registers the
  45. // callee is expected to save for the caller, with the exception of the stack
  46. // pointer. The stack pointer is tested implicitly by the function successfully
  47. // returning at all.
  48. #if defined(OPENSSL_X86_64)
  49. // References:
  50. // SysV64: https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf
  51. // Win64: https://docs.microsoft.com/en-us/cpp/build/x64-software-conventions?view=vs-2017#register-usage
  52. #if defined(OPENSSL_WINDOWS)
  53. #define LOOP_CALLER_STATE_REGISTERS() \
  54. CALLER_STATE_REGISTER(uint64_t, rbx) \
  55. CALLER_STATE_REGISTER(uint64_t, rbp) \
  56. CALLER_STATE_REGISTER(uint64_t, rdi) \
  57. CALLER_STATE_REGISTER(uint64_t, rsi) \
  58. CALLER_STATE_REGISTER(uint64_t, r12) \
  59. CALLER_STATE_REGISTER(uint64_t, r13) \
  60. CALLER_STATE_REGISTER(uint64_t, r14) \
  61. CALLER_STATE_REGISTER(uint64_t, r15) \
  62. CALLER_STATE_REGISTER(Reg128, xmm6) \
  63. CALLER_STATE_REGISTER(Reg128, xmm7) \
  64. CALLER_STATE_REGISTER(Reg128, xmm8) \
  65. CALLER_STATE_REGISTER(Reg128, xmm9) \
  66. CALLER_STATE_REGISTER(Reg128, xmm10) \
  67. CALLER_STATE_REGISTER(Reg128, xmm11) \
  68. CALLER_STATE_REGISTER(Reg128, xmm12) \
  69. CALLER_STATE_REGISTER(Reg128, xmm13) \
  70. CALLER_STATE_REGISTER(Reg128, xmm14) \
  71. CALLER_STATE_REGISTER(Reg128, xmm15)
  72. #else
  73. #define LOOP_CALLER_STATE_REGISTERS() \
  74. CALLER_STATE_REGISTER(uint64_t, rbx) \
  75. CALLER_STATE_REGISTER(uint64_t, rbp) \
  76. CALLER_STATE_REGISTER(uint64_t, r12) \
  77. CALLER_STATE_REGISTER(uint64_t, r13) \
  78. CALLER_STATE_REGISTER(uint64_t, r14) \
  79. CALLER_STATE_REGISTER(uint64_t, r15)
  80. #endif // OPENSSL_WINDOWS
  81. #elif defined(OPENSSL_X86)
  82. // References:
  83. // SysV32: https://uclibc.org/docs/psABI-i386.pdf and
  84. // Win32: https://docs.microsoft.com/en-us/cpp/cpp/argument-passing-and-naming-conventions?view=vs-2017
  85. #define LOOP_CALLER_STATE_REGISTERS() \
  86. CALLER_STATE_REGISTER(uint32_t, esi) \
  87. CALLER_STATE_REGISTER(uint32_t, edi) \
  88. CALLER_STATE_REGISTER(uint32_t, ebx) \
  89. CALLER_STATE_REGISTER(uint32_t, ebp)
  90. #elif defined(OPENSSL_ARM)
  91. // References:
  92. // AAPCS: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042f/IHI0042F_aapcs.pdf
  93. // iOS32: https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARMv6FunctionCallingConventions.html
  94. //
  95. // ARM specifies a common calling convention, except r9 is left to the
  96. // platform. Linux and iOS differ in handling of r9. iOS's behavior is defined
  97. // below. We found no clear reference for Linux but observed behavior from
  98. // LLVM. iOS 3+ treats r9 as caller-saved, while Linux treats it as
  99. // callee-saved. Most of our assembly treats it as callee-saved to be uniform,
  100. // but we match the platform to avoid false positives when testing
  101. // compiler-generated output.
  102. #define LOOP_CALLER_STATE_REGISTERS_PRE_R9() \
  103. CALLER_STATE_REGISTER(uint64_t, d8) \
  104. CALLER_STATE_REGISTER(uint64_t, d9) \
  105. CALLER_STATE_REGISTER(uint64_t, d10) \
  106. CALLER_STATE_REGISTER(uint64_t, d11) \
  107. CALLER_STATE_REGISTER(uint64_t, d12) \
  108. CALLER_STATE_REGISTER(uint64_t, d13) \
  109. CALLER_STATE_REGISTER(uint64_t, d14) \
  110. CALLER_STATE_REGISTER(uint64_t, d15) \
  111. CALLER_STATE_REGISTER(uint32_t, r4) \
  112. CALLER_STATE_REGISTER(uint32_t, r5) \
  113. CALLER_STATE_REGISTER(uint32_t, r6) \
  114. CALLER_STATE_REGISTER(uint32_t, r7) \
  115. CALLER_STATE_REGISTER(uint32_t, r8)
  116. #define LOOP_CALLER_STATE_REGISTERS_POST_R9() \
  117. CALLER_STATE_REGISTER(uint32_t, r10) \
  118. CALLER_STATE_REGISTER(uint32_t, r11)
  119. #if defined(OPENSSL_APPLE)
  120. #define LOOP_CALLER_STATE_REGISTERS() \
  121. LOOP_CALLER_STATE_REGISTERS_PRE_R9() \
  122. LOOP_CALLER_STATE_REGISTERS_POST_R9()
  123. #else // !OPENSSL_APPLE
  124. #define LOOP_CALLER_STATE_REGISTERS() \
  125. LOOP_CALLER_STATE_REGISTERS_PRE_R9() \
  126. CALLER_STATE_REGISTER(uint32_t, r9) \
  127. LOOP_CALLER_STATE_REGISTERS_POST_R9()
  128. #endif // OPENSSL_APPLE
  129. #elif defined(OPENSSL_AARCH64)
  130. // References:
  131. // AAPCS64: http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
  132. // iOS64: https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html
  133. //
  134. // In aarch64, r19 (x19 in a 64-bit context) is the platform register. iOS says
  135. // user code may not touch it. We found no clear reference for Linux. The iOS
  136. // behavior implies portable assembly cannot use it, and aarch64 has many
  137. // registers. Thus this framework ignores register's existence. We can test r19
  138. // violations with grep.
  139. #define LOOP_CALLER_STATE_REGISTERS() \
  140. /* Per AAPCS64, section 5.1.2, only the bottom 64 bits of v8-v15 */ \
  141. /* are preserved. These are accessed as dN. */ \
  142. CALLER_STATE_REGISTER(uint64_t, d8) \
  143. CALLER_STATE_REGISTER(uint64_t, d9) \
  144. CALLER_STATE_REGISTER(uint64_t, d10) \
  145. CALLER_STATE_REGISTER(uint64_t, d11) \
  146. CALLER_STATE_REGISTER(uint64_t, d12) \
  147. CALLER_STATE_REGISTER(uint64_t, d13) \
  148. CALLER_STATE_REGISTER(uint64_t, d14) \
  149. CALLER_STATE_REGISTER(uint64_t, d15) \
  150. /* For consistency with dN, use the 64-bit name xN, rather than */ \
  151. /* the generic rN. */ \
  152. CALLER_STATE_REGISTER(uint64_t, x19) \
  153. CALLER_STATE_REGISTER(uint64_t, x20) \
  154. CALLER_STATE_REGISTER(uint64_t, x21) \
  155. CALLER_STATE_REGISTER(uint64_t, x22) \
  156. CALLER_STATE_REGISTER(uint64_t, x23) \
  157. CALLER_STATE_REGISTER(uint64_t, x24) \
  158. CALLER_STATE_REGISTER(uint64_t, x25) \
  159. CALLER_STATE_REGISTER(uint64_t, x26) \
  160. CALLER_STATE_REGISTER(uint64_t, x27) \
  161. CALLER_STATE_REGISTER(uint64_t, x28) \
  162. CALLER_STATE_REGISTER(uint64_t, x29)
  163. #endif // X86_64 || X86 || ARM || AARCH64
  164. // Enable ABI testing if all of the following are true.
  165. //
  166. // - We have CallerState and trampoline support for the architecture.
  167. //
  168. // - Assembly is enabled.
  169. //
  170. // - This is not a shared library build. Assembly functions are not reachable
  171. // from tests in shared library builds.
  172. #if defined(LOOP_CALLER_STATE_REGISTERS) && !defined(OPENSSL_NO_ASM) && \
  173. !defined(BORINGSSL_SHARED_LIBRARY)
  174. #define SUPPORTS_ABI_TEST
  175. // CallerState contains all caller state that the callee is expected to
  176. // preserve.
  177. struct CallerState {
  178. #define CALLER_STATE_REGISTER(type, name) type name;
  179. LOOP_CALLER_STATE_REGISTERS()
  180. #undef CALLER_STATE_REGISTER
  181. };
  182. // RunTrampoline runs |func| on |argv|, recording ABI errors in |out|. It does
  183. // not perform any type-checking. If |unwind| is true and unwind tests have been
  184. // enabled, |func| is single-stepped under an unwind test.
  185. crypto_word_t RunTrampoline(Result *out, crypto_word_t func,
  186. const crypto_word_t *argv, size_t argc,
  187. bool unwind);
  188. template <typename T>
  189. inline crypto_word_t ToWord(T t) {
  190. #if !defined(OPENSSL_X86) && !defined(OPENSSL_X86_64) && \
  191. !defined(OPENSSL_ARM) && !defined(OPENSSL_AARCH64)
  192. #error "Unknown architecture"
  193. #endif
  194. static_assert(sizeof(T) <= sizeof(crypto_word_t),
  195. "T is larger than crypto_word_t");
  196. static_assert(sizeof(T) >= 4, "types under four bytes are complicated");
  197. // ABIs are complex around arguments that are smaller than native words. For
  198. // 32-bit architectures, the rules above imply we only have word-sized
  199. // arguments. For 64-bit architectures, we still have assembly functions which
  200. // take |int|.
  201. //
  202. // For aarch64, AAPCS64, section 5.4.2, clauses C.7 and C.14 says any
  203. // remaining bits are unspecified. iOS64 contradicts this and says the callee
  204. // extends arguments up to 32 bits, and only the upper 32 bits are
  205. // unspecified. Rejecting parameters smaller than 32 bits avoids the
  206. // divergence.
  207. //
  208. // TODO(davidben): Find authoritative citations for x86_64. For x86_64, I
  209. // observed the behavior of Clang, GCC, and MSVC. ABI rules here may be
  210. // inferred from two kinds of experiments:
  211. //
  212. // 1. When passing a value to a small-argument-taking function, does the
  213. // compiler ensure unused bits are cleared, sign-extended, etc.? Tests for
  214. // register parameters are confounded by x86_64's implicit clearing of
  215. // registers' upper halves, but passing some_u64 >> 1 usually clears this.
  216. //
  217. // 2. When compiling a small-argument-taking function, does the compiler make
  218. // assumptions about unused bits of arguments?
  219. //
  220. // MSVC for x86_64 is straightforward. It appears to tolerate and produce
  221. // arbitrary values for unused bits, like AAPCS64.
  222. //
  223. // GCC and Clang for x86_64 are more complex. They match MSVC for stack
  224. // parameters. However, for register parameters, they behave like iOS64 and,
  225. // as callers, extend up to 32 bits, leaving the remainder arbitrary. When
  226. // compiling a callee, Clang takes advantage of this conversion, but I was
  227. // unable to make GCC do so.
  228. //
  229. // Note that, although the Win64 rules are sufficient to require our assembly
  230. // be conservative, we wish for |CHECK_ABI| to support C-compiled functions,
  231. // so it must enforce the correct rules for each platform.
  232. //
  233. // Fortunately, the |static_assert|s above cause all supported architectures
  234. // to behave the same.
  235. crypto_word_t ret;
  236. // Filling extra bits with 0xaa will be vastly out of bounds for code
  237. // expecting either sign- or zero-extension. (0xaa is 0b10101010.)
  238. OPENSSL_memset(&ret, 0xaa, sizeof(ret));
  239. OPENSSL_memcpy(&ret, &t, sizeof(t));
  240. return ret;
  241. }
  242. // CheckImpl runs |func| on |args|, recording ABI errors in |out|. If |unwind|
  243. // is true and unwind tests have been enabled, |func| is single-stepped under an
  244. // unwind test.
  245. //
  246. // It returns the value as a |crypto_word_t| to work around problems when |R| is
  247. // void. |args| is wrapped in a |DeductionGuard| so |func| determines the
  248. // template arguments. Otherwise, |args| may deduce |Args| incorrectly. For
  249. // instance, if |func| takes const int *, and the caller passes an int *, the
  250. // compiler will complain the deduced types do not match.
  251. template <typename R, typename... Args>
  252. inline crypto_word_t CheckImpl(Result *out, bool unwind, R (*func)(Args...),
  253. typename DeductionGuard<Args>::Type... args) {
  254. // We only support up to 8 arguments. This ensures all arguments on aarch64
  255. // are passed in registers and avoids the iOS descrepancy around packing small
  256. // arguments on the stack.
  257. //
  258. // https://developer.apple.com/library/archive/documentation/Xcode/Conceptual/iPhoneOSABIReference/Articles/ARM64FunctionCallingConventions.html
  259. static_assert(sizeof...(args) <= 8,
  260. "too many arguments for abi_test_trampoline");
  261. // Allocate one extra entry so MSVC does not complain about zero-size arrays.
  262. crypto_word_t argv[sizeof...(args) + 1] = {
  263. ToWord(args)...,
  264. };
  265. return RunTrampoline(out, reinterpret_cast<crypto_word_t>(func), argv,
  266. sizeof...(args), unwind);
  267. }
  268. #else
  269. // To simplify callers when ABI testing support is unavoidable, provide a backup
  270. // CheckImpl implementation. It must be specialized for void returns because we
  271. // call |func| directly.
  272. template <typename R, typename... Args>
  273. inline typename std::enable_if<!std::is_void<R>::value, crypto_word_t>::type
  274. CheckImpl(Result *out, bool /* unwind */, R (*func)(Args...),
  275. typename DeductionGuard<Args>::Type... args) {
  276. *out = Result();
  277. return func(args...);
  278. }
  279. template <typename... Args>
  280. inline crypto_word_t CheckImpl(Result *out, bool /* unwind */,
  281. void (*func)(Args...),
  282. typename DeductionGuard<Args>::Type... args) {
  283. *out = Result();
  284. func(args...);
  285. return 0;
  286. }
  287. #endif // SUPPORTS_ABI_TEST
  288. // FixVAArgsString takes a string like "f, 1, 2" and returns a string like
  289. // "f(1, 2)".
  290. //
  291. // This is needed because the |CHECK_ABI| macro below cannot be defined as
  292. // CHECK_ABI(func, ...). The C specification requires that variadic macros bind
  293. // at least one variadic argument. Clang, GCC, and MSVC all ignore this, but
  294. // there are issues with trailing commas and different behaviors across
  295. // compilers.
  296. std::string FixVAArgsString(const char *str);
  297. // CheckGTest behaves like |CheckImpl|, but it returns the correct type and
  298. // raises GTest assertions on failure. If |unwind| is true and unwind tests are
  299. // enabled, |func| is single-stepped under an unwind test.
  300. template <typename R, typename... Args>
  301. inline R CheckGTest(const char *va_args_str, const char *file, int line,
  302. bool unwind, R (*func)(Args...),
  303. typename DeductionGuard<Args>::Type... args) {
  304. Result result;
  305. crypto_word_t ret = CheckImpl(&result, unwind, func, args...);
  306. if (!result.ok()) {
  307. testing::Message msg;
  308. msg << "ABI failures in " << FixVAArgsString(va_args_str) << ":\n";
  309. for (const auto &error : result.errors) {
  310. msg << " " << error << "\n";
  311. }
  312. ADD_FAILURE_AT(file, line) << msg;
  313. }
  314. return (R)ret;
  315. }
  316. } // namespace internal
  317. // Check runs |func| on |args| and returns the result. If ABI-testing is
  318. // supported in this build configuration, it writes any ABI failures to |out|.
  319. // Otherwise, it runs the function transparently.
  320. template <typename R, typename... Args>
  321. inline R Check(Result *out, R (*func)(Args...),
  322. typename internal::DeductionGuard<Args>::Type... args) {
  323. return (R)internal::CheckImpl(out, false, func, args...);
  324. }
  325. // EnableUnwindTests enables unwind tests, if supported. If not supported, it
  326. // does nothing.
  327. void EnableUnwindTests();
  328. // UnwindTestsEnabled returns true if unwind tests are enabled and false
  329. // otherwise.
  330. bool UnwindTestsEnabled();
  331. } // namespace abi_test
  332. // CHECK_ABI calls the first argument on the remaining arguments and returns the
  333. // result. If ABI-testing is supported in this build configuration, it adds a
  334. // non-fatal GTest failure if the call did not satisfy ABI requirements.
  335. //
  336. // |CHECK_ABI| does return the value and thus may replace any function call,
  337. // provided it takes only simple parameters. However, it is recommended to test
  338. // ABI separately from functional tests of assembly. Fully instrumenting a
  339. // function for ABI checking requires single-stepping the function, which is
  340. // inefficient.
  341. //
  342. // Functional testing requires coverage of input values, while ABI testing only
  343. // requires branch coverage. Most of our assembly is constant-time, so usually
  344. // only a few instrumented calls are necessary.
  345. //
  346. // TODO(https://crbug.com/boringssl/259): Most of Windows assembly currently
  347. // fails SEH testing. For now, |CHECK_ABI| behaves like |CHECK_ABI_NO_UNWIND|
  348. // on Windows. Functions which work with unwind testing on Windows should use
  349. // |CHECK_ABI_SEH|.
  350. #if defined(OPENSSL_WINDOWS)
  351. #define CHECK_ABI(...) CHECK_ABI_NO_UNWIND(__VA_ARGS__)
  352. #else
  353. #define CHECK_ABI(...) CHECK_ABI_SEH(__VA_ARGS__)
  354. #endif
  355. // CHECK_ABI_SEH behaves like |CHECK_ABI| but enables unwind testing on Windows.
  356. #define CHECK_ABI_SEH(...) \
  357. abi_test::internal::CheckGTest(#__VA_ARGS__, __FILE__, __LINE__, true, \
  358. __VA_ARGS__)
  359. // CHECK_ABI_NO_UNWIND behaves like |CHECK_ABI| but disables unwind testing.
  360. #define CHECK_ABI_NO_UNWIND(...) \
  361. abi_test::internal::CheckGTest(#__VA_ARGS__, __FILE__, __LINE__, false, \
  362. __VA_ARGS__)
  363. // Internal functions.
  364. #if defined(SUPPORTS_ABI_TEST)
  365. struct Uncallable {
  366. Uncallable() = delete;
  367. };
  368. extern "C" {
  369. // abi_test_trampoline loads callee-saved registers from |state|, calls |func|
  370. // with |argv|, then saves the callee-saved registers into |state|. It returns
  371. // the result of |func|. If |unwind| is non-zero, this function triggers unwind
  372. // instrumentation.
  373. //
  374. // We give |func| type |crypto_word_t| to avoid tripping MSVC's warning 4191.
  375. crypto_word_t abi_test_trampoline(crypto_word_t func,
  376. abi_test::internal::CallerState *state,
  377. const crypto_word_t *argv, size_t argc,
  378. crypto_word_t unwind);
  379. #if defined(OPENSSL_X86_64)
  380. // abi_test_unwind_start points at the instruction that starts unwind testing in
  381. // |abi_test_trampoline|. This is the value of the instruction pointer at the
  382. // first |SIGTRAP| during unwind testing.
  383. //
  384. // This symbol is not a function and should not be called.
  385. void abi_test_unwind_start(Uncallable);
  386. // abi_test_unwind_return points at the instruction immediately after the call in
  387. // |abi_test_trampoline|. When unwinding the function under test, this is the
  388. // expected address in the |abi_test_trampoline| frame. After this address, the
  389. // unwind tester should ignore |SIGTRAP| until |abi_test_unwind_stop|.
  390. //
  391. // This symbol is not a function and should not be called.
  392. void abi_test_unwind_return(Uncallable);
  393. // abi_test_unwind_stop is the value of the instruction pointer at the final
  394. // |SIGTRAP| during unwind testing.
  395. //
  396. // This symbol is not a function and should not be called.
  397. void abi_test_unwind_stop(Uncallable);
  398. // abi_test_bad_unwind_wrong_register preserves the ABI, but annotates the wrong
  399. // register in unwind metadata.
  400. void abi_test_bad_unwind_wrong_register(void);
  401. // abi_test_bad_unwind_temporary preserves the ABI, but temporarily corrupts the
  402. // storage space for a saved register, breaking unwind.
  403. void abi_test_bad_unwind_temporary(void);
  404. #if defined(OPENSSL_WINDOWS)
  405. // abi_test_bad_unwind_epilog preserves the ABI, and correctly annotates the
  406. // prolog, but the epilog does not match Win64's rules, breaking unwind during
  407. // the epilog.
  408. void abi_test_bad_unwind_epilog(void);
  409. #endif
  410. #endif // OPENSSL_X86_64
  411. #if defined(OPENSSL_X86_64) || defined(OPENSSL_X86)
  412. // abi_test_get_and_clear_direction_flag clears the direction flag. If the flag
  413. // was previously set, it returns one. Otherwise, it returns zero.
  414. int abi_test_get_and_clear_direction_flag(void);
  415. // abi_test_set_direction_flag sets the direction flag. This does not conform to
  416. // ABI requirements and must only be called within a |CHECK_ABI| guard to avoid
  417. // errors later in the program.
  418. int abi_test_set_direction_flag(void);
  419. #endif // OPENSSL_X86_64 || OPENSSL_X86
  420. } // extern "C"
  421. #endif // SUPPORTS_ABI_TEST
  422. #endif // OPENSSL_HEADER_ABI_TEST_H