| Index: ppapi/tests/test_nacl_irt_stack_alignment.cc
|
| diff --git a/ppapi/tests/test_nacl_irt_stack_alignment.cc b/ppapi/tests/test_nacl_irt_stack_alignment.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5b379c42a3f929b33ba0c331eeb57561a424807b
|
| --- /dev/null
|
| +++ b/ppapi/tests/test_nacl_irt_stack_alignment.cc
|
| @@ -0,0 +1,85 @@
|
| +// Copyright (c) 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "ppapi/tests/test_nacl_irt_stack_alignment.h"
|
| +
|
| +#include "ppapi/c/pp_var.h"
|
| +#include "ppapi/c/ppb_var.h"
|
| +#include "ppapi/cpp/instance.h"
|
| +#include "ppapi/cpp/module.h"
|
| +#include "ppapi/cpp/var.h"
|
| +#include "ppapi/tests/testing_instance.h"
|
| +
|
| +// This whole test is really only meant for x86-32 NaCl (not PNaCl).
|
| +//
|
| +// This is a regression test for the IRT code being sensitive to stack
|
| +// alignment. The de jure ABI is that the stack should be aligned to
|
| +// 16 bytes at call sites. However, the de facto ABI is that the IRT
|
| +// worked in the past when called with misaligned stack. NaCl code is
|
| +// now compiled to expect the proper 16-byte alignment, but the IRT
|
| +// code must remain compatible with old binaries that failed to do so.
|
| +
|
| +#if defined(__i386__)
|
| +
|
| +REGISTER_TEST_CASE(NaClIRTStackAlignment);
|
| +
|
| +bool TestNaClIRTStackAlignment::Init() {
|
| + var_interface_ = static_cast<const PPB_Var*>(
|
| + pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE));
|
| + return var_interface_ && CheckTestingInterface();
|
| +}
|
| +
|
| +void TestNaClIRTStackAlignment::RunTests(const std::string& filter) {
|
| + RUN_TEST(MisalignedCallVarAddRef, filter);
|
| +}
|
| +
|
| +// This calls the given function with the stack explicitly misaligned.
|
| +// If the function (in the IRT) was compiled wrongly, it will crash.
|
| +void MisalignedCall(void (*func)(PP_Var), const PP_Var* arg)
|
| + asm("MisalignedCall") __attribute__((regparm(2)));
|
| +
|
| +// regparm(2) means: First argument in %eax, second argument in %edx.
|
| +// Writing this with an inline asm would require explaining all the
|
| +// call-clobbers register behavior in the asm clobber list, which is a
|
| +// lot with all the SSE and FPU state. It's far simpler just to make
|
| +// it a function call the compiler knows is a function call, and then
|
| +// write the function itself in pure assembly.
|
| +asm("MisalignedCall:\n"
|
| + // Use an SSE register to copy the 16 bytes of memory.
|
| + // Note this instruction does not care about alignment.
|
| + // The pointer is not necessarily aligned to 16 bytes.
|
| + "movups (%edx), %xmm0\n"
|
| + // Set up a frame so we can recover the stack pointer after alignment.
|
| + "push %ebp\n"
|
| + "mov %esp, %ebp\n"
|
| + // Align the stack properly to 16 bytes.
|
| + "andl $-16, %esp\n"
|
| + // Now make space for the 16 bytes of argument data,
|
| + // plus another 4 bytes so the stack pointer is misaligned.
|
| + "subl $20, %esp\n"
|
| + // Copy the argument onto the (misaligned) top of stack.
|
| + "movups %xmm0, (%esp)\n"
|
| + // Now call into the IRT, and hilarity ensues.
|
| + "naclcall %eax\n"
|
| + // Standard epilogue.
|
| + "mov %ebp, %esp\n"
|
| + "pop %ebp\n"
|
| + "naclret");
|
| +
|
| +std::string TestNaClIRTStackAlignment::TestMisalignedCallVarAddRef() {
|
| + PP_Var var;
|
| + var.type = PP_VARTYPE_INT32;
|
| + var.padding = 0;
|
| + var.value.as_int = 23;
|
| +
|
| + ASSERT_EQ(sizeof(var), static_cast<size_t>(16));
|
| +
|
| + // This will crash if the test fails.
|
| + MisalignedCall(var_interface_->AddRef, &var);
|
| + MisalignedCall(var_interface_->Release, &var);
|
| +
|
| + PASS();
|
| +}
|
| +
|
| +#endif // defined(__i386__)
|
|
|