Save trampoline state in unwind tests more straightforwardly Rather than sample it from the UnwindCursor, we can just save it immediately before starting the test. Change-Id: Ica1eaa215755b0b772eaa08e03c5885aacec4f70 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/62866 Auto-Submit: David Benjamin <davidben@google.com> Reviewed-by: Adam Langley <agl@google.com> Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/test/abi_test.cc b/crypto/test/abi_test.cc index 536be3c..2338258 100644 --- a/crypto/test/abi_test.cc +++ b/crypto/test/abi_test.cc
@@ -87,43 +87,6 @@ LOOP_CALLER_STATE_REGISTERS() #undef CALLER_STATE_REGISTER } - -// ReadUnwindResult adds the results of the most recent unwind test to |out|. -static void ReadUnwindResult(Result *out); - -crypto_word_t RunTrampoline(Result *out, crypto_word_t func, - const crypto_word_t *argv, size_t argc, - bool unwind) { - CallerState state; - RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state)); - - unwind &= g_unwind_tests_enabled; - CallerState state2 = state; - crypto_word_t ret = abi_test_trampoline(func, &state2, argv, argc, unwind); -#if defined(OPENSSL_X86_64) || defined(OPENSSL_X86) - // Query and clear the direction flag early, so negative tests do not - // interfere with |malloc|. - bool direction_flag = abi_test_get_and_clear_direction_flag(); -#endif // OPENSSL_X86_64 || OPENSSL_X86 - - *out = Result(); - ForEachMismatch(state, state2, [&](const char *reg) { - out->errors.push_back(std::string(reg) + " was not restored after return"); - }); -#if defined(OPENSSL_X86_64) || defined(OPENSSL_X86) - // Linux and Windows ABIs for x86 require the direction flag be cleared on - // return. (Some OpenSSL assembly preserves it, which is stronger, but we only - // require what is specified by the ABI so |CHECK_ABI| works with C compiler - // output.) - if (direction_flag) { - out->errors.emplace_back("Direction flag set after return"); - } -#endif // OPENSSL_X86_64 || OPENSSL_X86 - if (unwind) { - ReadUnwindResult(out); - } - return ret; -} #endif // SUPPORTS_ABI_TEST #if defined(SUPPORTS_UNWIND_TEST) @@ -474,8 +437,8 @@ // g_unwind_function_done, if |g_in_trampoline| is true, is whether the function // under test has returned. It is undefined otherwise. static bool g_unwind_function_done; -// g_trampoline_state, if |g_in_trampoline| is true, is the state the function -// under test must preserve. It is undefined otherwise. +// g_trampoline_state, during an unwind-enabled ABI test, is the state the +// function under test must preserve. It is undefined otherwise. static CallerState g_trampoline_state; // g_trampoline_sp, if |g_in_trampoline| is true, is the stack pointer of the // trampoline frame. It is undefined otherwise. @@ -536,8 +499,6 @@ g_in_trampoline = true; g_unwind_function_done = false; g_trampoline_sp = sp; - g_trampoline_state = cursor->GetCallerState().ValueOrDie( - "Error getting initial caller state"); } else { if (sp == g_trampoline_sp || g_unwind_function_done) { // |g_unwind_function_done| should imply |sp| is |g_trampoline_sp|, but @@ -608,6 +569,7 @@ } } +// ReadUnwindResult adds the results of the most recent unwind test to |out|. static void ReadUnwindResult(Result *out) { for (size_t i = 0; i < g_num_unwind_errors; i++) { #if defined(OPENSSL_WINDOWS) @@ -784,6 +746,48 @@ #endif // SUPPORTS_UNWIND_TEST +#if defined(SUPPORTS_ABI_TEST) +crypto_word_t RunTrampoline(Result *out, crypto_word_t func, + const crypto_word_t *argv, size_t argc, + bool unwind) { + CallerState state; + RAND_bytes(reinterpret_cast<uint8_t *>(&state), sizeof(state)); + + unwind &= g_unwind_tests_enabled; +#if defined(SUPPORTS_UNWIND_TEST) + if (unwind) { + // Save the caller state for the unwind tester to check for. + g_trampoline_state = state; + } +#endif + CallerState state2 = state; + crypto_word_t ret = abi_test_trampoline(func, &state2, argv, argc, unwind); +#if defined(OPENSSL_X86_64) || defined(OPENSSL_X86) + // Query and clear the direction flag early, so negative tests do not + // interfere with |malloc|. + bool direction_flag = abi_test_get_and_clear_direction_flag(); +#endif // OPENSSL_X86_64 || OPENSSL_X86 + + *out = Result(); + ForEachMismatch(state, state2, [&](const char *reg) { + out->errors.push_back(std::string(reg) + " was not restored after return"); + }); +#if defined(OPENSSL_X86_64) || defined(OPENSSL_X86) + // Linux and Windows ABIs for x86 require the direction flag be cleared on + // return. (Some OpenSSL assembly preserves it, which is stronger, but we only + // require what is specified by the ABI so |CHECK_ABI| works with C compiler + // output.) + if (direction_flag) { + out->errors.emplace_back("Direction flag set after return"); + } +#endif // OPENSSL_X86_64 || OPENSSL_X86 + if (unwind) { + ReadUnwindResult(out); + } + return ret; +} +#endif // SUPPORTS_ABI_TEST + } // namespace internal void EnableUnwindTests() { internal::EnableUnwindTestsImpl(); }