diff options
author | Jacob Bramley <jacob.bramley@arm.com> | 2020-10-30 18:25:43 +0000 |
---|---|---|
committer | Jacob Bramley <jacob.bramley@arm.com> | 2020-11-05 14:34:47 +0000 |
commit | c4ef66e95e71f13cb4f1d2983d401fe49bdcc0a7 (patch) | |
tree | 7d1be638b0813c5a1358f528626046411567a339 /test | |
parent | f73036bad9bdb8c853d783c7f94be1f298cb508d (diff) | |
download | vixl-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.cc | 56 | ||||
-rw-r--r-- | test/aarch64/test-assembler-aarch64.cc | 115 | ||||
-rw-r--r-- | test/aarch64/test-assembler-aarch64.h | 22 |
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(); \ |