blob: 8dd7b529e49d4a6e5512c8aba6f47fc95d52b60f [file] [log] [blame] [edit]
// Copyright 2020 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/unittest/unittest.h>
#include <stddef.h>
#include <stdint.h>
namespace {
constexpr size_t kStackAlignment = 16;
#if defined(__aarch64__) && defined(__PE_COFF__)
// On Aarch64 Windows, the frame pointer is the SP after pushing one word.
// This differs from other targets, since Windows reverses the order of the
// stack when SVE is enabled.
// See:
// - Microsoft ARM64 ABI:
// https://docs.microsoft.com/en-us/cpp/build/arm64-windows-abi?view=msvc-170
// - AArch64 Windows ABI and SVE:
// https://devblogs.microsoft.com/cppblog/aarch64-windows-abi-and-sve/
constexpr size_t kFpAdjust = sizeof(uintptr_t);
#else
// The frame pointer is the SP after pushing two words.
// This differs mod 16 when using 32-bit words (x86-32).
constexpr size_t kFpAdjust = 2 * sizeof(uintptr_t);
#endif
bool StackAligned(void* ptr, bool fp) {
// Make sure the compiler doesn't think it knows the value,
// so there will be a runtime check.
uintptr_t stack_addr;
__asm__("" : "=g"(stack_addr) : "0"(ptr));
if (fp) {
stack_addr += kFpAdjust;
}
return stack_addr % kStackAlignment == 0;
}
bool stack_alignment() {
BEGIN_TEST;
void* machine_stack = __builtin_frame_address(0);
EXPECT_TRUE(StackAligned(machine_stack, true));
#if __has_feature(safe_stack)
alignas(kStackAlignment) char unsafe_stack[1] = {17};
EXPECT_TRUE(StackAligned(unsafe_stack, false));
#endif
END_TEST;
}
} // namespace
UNITTEST_START_TESTCASE(stack_tests)
UNITTEST("stack alignment", stack_alignment)
UNITTEST_END_TESTCASE(stack_tests, "stack", "stack tests")