Skip to content

Commit

Permalink
Save trampoline state in unwind tests more straightforwardly
Browse files Browse the repository at this point in the history
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>
(cherry picked from commit 79532afc453d5400be886ee7ba9ecb92451a573e)
  • Loading branch information
davidben authored and torben-hansen committed Jan 30, 2024
1 parent a71932a commit c12cc40
Showing 1 changed file with 45 additions and 41 deletions.
86 changes: 45 additions & 41 deletions crypto/test/abi_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -88,43 +88,6 @@ static void ForEachMismatch(const CallerState &a, const CallerState &b,
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)
Expand Down Expand Up @@ -473,8 +436,8 @@ static bool g_in_trampoline = false;
// 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.
Expand Down Expand Up @@ -535,8 +498,6 @@ static void CheckUnwind(UnwindCursor *cursor) {
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
Expand Down Expand Up @@ -607,6 +568,7 @@ static void CheckUnwind(UnwindCursor *cursor) {
}
}

// 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)
Expand Down Expand Up @@ -783,6 +745,48 @@ static void EnableUnwindTestsImpl() {}

#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(); }
Expand Down

0 comments on commit c12cc40

Please sign in to comment.