aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorJacob Bramley <jacob.bramley@arm.com>2020-10-30 18:25:43 +0000
committerJacob Bramley <jacob.bramley@arm.com>2020-11-05 14:34:47 +0000
commitc4ef66e95e71f13cb4f1d2983d401fe49bdcc0a7 (patch)
tree7d1be638b0813c5a1358f528626046411567a339 /test
parentf73036bad9bdb8c853d783c7f94be1f298cb508d (diff)
downloadvixl-c4ef66e95e71f13cb4f1d2983d401fe49bdcc0a7.tar.gz
Make the stack size configurable.
Also fix the implementation of stack guards, and make these configurable too. Change-Id: Ic62ee326ed725616322ca8fa26d38b9a089d5043
Diffstat (limited to 'test')
-rw-r--r--test/aarch64/test-api-aarch64.cc56
-rw-r--r--test/aarch64/test-assembler-aarch64.cc115
-rw-r--r--test/aarch64/test-assembler-aarch64.h22
3 files changed, 188 insertions, 5 deletions
diff --git a/test/aarch64/test-api-aarch64.cc b/test/aarch64/test-api-aarch64.cc
index 445c0bf2..b2a7f663 100644
--- a/test/aarch64/test-api-aarch64.cc
+++ b/test/aarch64/test-api-aarch64.cc
@@ -34,6 +34,7 @@
#include "aarch64/macro-assembler-aarch64.h"
#include "aarch64/registers-aarch64.h"
+#include "aarch64/simulator-aarch64.h"
#define __ masm.
#define TEST(name) TEST_(AARCH64_API_##name)
@@ -1709,5 +1710,60 @@ TEST(scratch_scope_release_p) {
}
}
+#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
+TEST(sim_stack_default) {
+ SimStack::Allocated s = SimStack().Allocate();
+
+ // The default stack is at least 16-byte aligned.
+ VIXL_CHECK(IsAligned<16>(s.GetBase()));
+ VIXL_CHECK(IsAligned<16>(s.GetLimit() + 1));
+
+ VIXL_CHECK(s.GetBase() > s.GetLimit());
+
+ // The default guard regions are sufficient to detect at least off-by-one
+ // errors.
+ VIXL_CHECK(s.IsAccessInGuardRegion(s.GetBase(), 1));
+ VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetBase() - 1, 1));
+ // The limit is one below the lowest address on the stack.
+ VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit(), 1));
+ VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetLimit() + 1, 1));
+
+ // We need to be able to access 16-byte granules at both extremes.
+ VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetBase() - 16, 16));
+ VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetLimit() + 1, 16));
+}
+
+TEST(sim_stack) {
+ SimStack builder;
+ builder.AlignToBytesLog2(WhichPowerOf2(1024));
+ builder.SetBaseGuardSize(42);
+ builder.SetLimitGuardSize(2049);
+ builder.SetUsableSize(2048);
+ SimStack::Allocated s = builder.Allocate();
+
+ VIXL_CHECK(IsAligned<1024>(s.GetBase()));
+ VIXL_CHECK(IsAligned<1024>(s.GetLimit() + 1));
+
+ // The stack is accessible for (limit, base), both exclusive.
+ // This is checked precisely, using the base and limit modified to respect
+ // alignment, so we can test the exact boundary condition.
+ VIXL_CHECK(s.IsAccessInGuardRegion(s.GetBase(), 1));
+ VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetBase() - 1, 1));
+ VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit(), 1));
+ VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetLimit() + 1, 1));
+ VIXL_CHECK((s.GetBase() - s.GetLimit() - 1) == 2048);
+
+ // We can access the whole range (limit, base), both exclusive.
+ VIXL_CHECK(!s.IsAccessInGuardRegion(s.GetLimit() + 1, 2048));
+ // Off-by-one.
+ VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit(), 2048));
+ VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit() + 1, 2049));
+ // Accesses spanning whole guard regions.
+ VIXL_CHECK(s.IsAccessInGuardRegion(s.GetBase() - 42, 4096));
+ VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit() - 1280, 2048));
+ VIXL_CHECK(s.IsAccessInGuardRegion(s.GetLimit() - 1280, 10000));
+}
+#endif
+
} // namespace aarch64
} // namespace vixl
diff --git a/test/aarch64/test-assembler-aarch64.cc b/test/aarch64/test-assembler-aarch64.cc
index e75ab599..8f73127d 100644
--- a/test/aarch64/test-assembler-aarch64.cc
+++ b/test/aarch64/test-assembler-aarch64.cc
@@ -13569,7 +13569,122 @@ static void SimulationCPUFeaturesScopeHelper(const CPUFeatures& base,
TEST(configure_cpu_features_scope) {
RunHelperWithFeatureCombinations(SimulationCPUFeaturesScopeHelper);
}
+#endif
+
+
+#ifdef VIXL_INCLUDE_SIMULATOR_AARCH64
+TEST(large_sim_stack) {
+ SimStack builder;
+ builder.SetUsableSize(16 * 1024); // The default is 8kB.
+ SimStack::Allocated stack = builder.Allocate();
+ uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
+ uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
+ SETUP_CUSTOM_SIM(std::move(stack));
+ START();
+
+ // Check that we can access the extremes of the stack.
+ __ Mov(x0, base);
+ __ Mov(x1, limit);
+ __ Mov(x2, sp);
+ __ Add(sp, x1, 1); // Avoid accessing memory below `sp`.
+
+ __ Mov(x10, 42);
+ __ Poke(x10, 0);
+ __ Peek(x10, base - limit - kXRegSizeInBytes - 1);
+
+ __ Mov(sp, x2);
+
+ END();
+ if (CAN_RUN()) {
+ RUN();
+ }
+}
+
+#ifdef VIXL_NEGATIVE_TESTING
+TEST(sim_stack_limit_guard_read) {
+ SimStack builder;
+ SimStack::Allocated stack = builder.Allocate();
+ uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
+ SETUP_CUSTOM_SIM(std::move(stack));
+ START();
+
+ __ Mov(x1, limit);
+ __ Mov(x2, sp);
+ __ Add(sp, x1, 1); // Avoid accessing memory below `sp`.
+
+ // `sp` points to the lowest usable byte of the stack.
+ __ Mov(w10, 42);
+ __ Ldrb(w10, MemOperand(sp, -1));
+
+ __ Mov(sp, x2);
+
+ END();
+ if (CAN_RUN()) {
+ MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to read from stack guard region");
+ }
+}
+
+TEST(sim_stack_limit_guard_write) {
+ SimStack builder;
+ SimStack::Allocated stack = builder.Allocate();
+ uintptr_t limit = reinterpret_cast<uintptr_t>(stack.GetLimit());
+ SETUP_CUSTOM_SIM(std::move(stack));
+ START();
+
+ __ Mov(x1, limit);
+ __ Mov(x2, sp);
+ __ Add(sp, x1, 1); // Avoid accessing memory below `sp`.
+
+ // `sp` points to the lowest usable byte of the stack.
+ __ Mov(w10, 42);
+ __ Strb(w10, MemOperand(sp, -1));
+
+ __ Mov(sp, x2);
+
+ END();
+ if (CAN_RUN()) {
+ MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to write to stack guard region");
+ }
+}
+
+TEST(sim_stack_base_guard_read) {
+ SimStack builder;
+ SimStack::Allocated stack = builder.Allocate();
+ uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
+ SETUP_CUSTOM_SIM(std::move(stack));
+ START();
+
+ __ Mov(x0, base);
+ // `base` (x0) is the byte after the highest usable byte of the stack.
+ // The last byte of this access will hit the guard region.
+ __ Mov(x10, 42);
+ __ Ldr(x10, MemOperand(x0, -static_cast<int64_t>(kXRegSizeInBytes) + 1));
+ END();
+ if (CAN_RUN()) {
+ MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to read from stack guard region");
+ }
+}
+
+TEST(sim_stack_base_guard_write) {
+ SimStack builder;
+ SimStack::Allocated stack = builder.Allocate();
+ uintptr_t base = reinterpret_cast<uintptr_t>(stack.GetBase());
+ SETUP_CUSTOM_SIM(std::move(stack));
+ START();
+
+ __ Mov(x0, base);
+ // `base` (x0) is the byte after the highest usable byte of the stack.
+ // The last byte of this access will hit the guard region.
+ __ Mov(x10, 42);
+ __ Str(x10, MemOperand(x0, -static_cast<int64_t>(kXRegSizeInBytes) + 1));
+
+ END();
+ if (CAN_RUN()) {
+ MUST_FAIL_WITH_MESSAGE(RUN(), "Attempt to write to stack guard region");
+ }
+}
+#endif
#endif
} // namespace aarch64
diff --git a/test/aarch64/test-assembler-aarch64.h b/test/aarch64/test-assembler-aarch64.h
index fac018e9..31e926dd 100644
--- a/test/aarch64/test-assembler-aarch64.h
+++ b/test/aarch64/test-assembler-aarch64.h
@@ -85,17 +85,27 @@ namespace aarch64 {
#define SETUP() \
MacroAssembler masm; \
- SETUP_COMMON()
+ SETUP_COMMON(); \
+ SETUP_COMMON_SIM()
#define SETUP_WITH_FEATURES(...) \
MacroAssembler masm; \
SETUP_COMMON(); \
+ SETUP_COMMON_SIM(); \
masm.SetCPUFeatures(CPUFeatures(__VA_ARGS__)); \
simulator.SetCPUFeatures(CPUFeatures(__VA_ARGS__))
#define SETUP_CUSTOM(size, pic) \
MacroAssembler masm(size + CodeBuffer::kDefaultCapacity, pic); \
- SETUP_COMMON()
+ SETUP_COMMON(); \
+ SETUP_COMMON_SIM()
+
+#define SETUP_CUSTOM_SIM(...) \
+ MacroAssembler masm; \
+ SETUP_COMMON(); \
+ Simulator simulator(&simulator_decoder, stdout, __VA_ARGS__); \
+ simulator.SetColouredTrace(Test::coloured_trace()); \
+ simulator.SetCPUFeatures(CPUFeatures::None())
#define SETUP_COMMON() \
bool queried_can_run = false; \
@@ -106,13 +116,15 @@ namespace aarch64 {
masm.SetCPUFeatures(CPUFeatures::None()); \
masm.SetGenerateSimulatorCode(true); \
Decoder simulator_decoder; \
- Simulator simulator(&simulator_decoder); \
- simulator.SetColouredTrace(Test::coloured_trace()); \
- simulator.SetCPUFeatures(CPUFeatures::None()); \
RegisterDump core; \
ptrdiff_t offset_after_infrastructure_start; \
ptrdiff_t offset_before_infrastructure_end
+#define SETUP_COMMON_SIM() \
+ Simulator simulator(&simulator_decoder); \
+ simulator.SetColouredTrace(Test::coloured_trace()); \
+ simulator.SetCPUFeatures(CPUFeatures::None())
+
#define START() \
masm.Reset(); \
simulator.ResetState(); \