summaryrefslogtreecommitdiffstats
path: root/ppapi
diff options
context:
space:
mode:
authormcgrathr <mcgrathr@chromium.org>2015-10-02 14:54:42 -0700
committerCommit bot <commit-bot@chromium.org>2015-10-02 21:56:35 +0000
commit892faf25eff4691860da127aab8b71c0bcdfa3b9 (patch)
treeb552997af14ff9c6a83c90a986e71853181100ee /ppapi
parent3862a3e5baf3e0e5c867d82df6615414ae914855 (diff)
downloadchromium_src-892faf25eff4691860da127aab8b71c0bcdfa3b9.zip
chromium_src-892faf25eff4691860da127aab8b71c0bcdfa3b9.tar.gz
chromium_src-892faf25eff4691860da127aab8b71c0bcdfa3b9.tar.bz2
PPAPI regression test for NaCl x86-32 IRT stack alignment sensitivity
The bug with IRT stack alignment sensitivity can manifest in two ways. The issue of the stack being aligned properly at callbacks from the IRT is tested on the NaCl side (irt_stack_alignment test). The other issue is alignment-sensitive SSE instructions being used to copy 16-byte arguments from the stack, assuming they will be properly aligned on the stack. That situation only comes up with the PPAPI interfaces that use a 16-byte argument type such as PP_Var. So test that case here. BUG= https://code.google.com/p/nativeclient/issues/detail?id=3935 TEST= browser_tests --gtest_filter=PPAPINaClNewlibTest.NaClIRTStackAlignment on x86-32 R=bbudge@chromium.org, dschuff@chromium.org Review URL: https://codereview.chromium.org/1384583006 Cr-Commit-Position: refs/heads/master@{#352146}
Diffstat (limited to 'ppapi')
-rw-r--r--ppapi/ppapi_sources.gypi2
-rw-r--r--ppapi/tests/test_nacl_irt_stack_alignment.cc85
-rw-r--r--ppapi/tests/test_nacl_irt_stack_alignment.h30
3 files changed, 117 insertions, 0 deletions
diff --git a/ppapi/ppapi_sources.gypi b/ppapi/ppapi_sources.gypi
index 55e1ff2..ea7ccbb 100644
--- a/ppapi/ppapi_sources.gypi
+++ b/ppapi/ppapi_sources.gypi
@@ -513,6 +513,8 @@
#
'test_nacl_source_files': [
# Test cases (PLEASE KEEP THIS SECTION IN ALPHABETICAL ORDER)
+ 'tests/test_nacl_irt_stack_alignment.cc',
+ 'tests/test_nacl_irt_stack_alignment.h',
'tests/test_tcp_server_socket_private_disallowed.cc',
'tests/test_tcp_socket_private_disallowed.cc',
'tests/test_udp_socket_private_disallowed.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 0000000..5b379c4
--- /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__)
diff --git a/ppapi/tests/test_nacl_irt_stack_alignment.h b/ppapi/tests/test_nacl_irt_stack_alignment.h
new file mode 100644
index 0000000..61de76f
--- /dev/null
+++ b/ppapi/tests/test_nacl_irt_stack_alignment.h
@@ -0,0 +1,30 @@
+// 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.
+
+#ifndef PPAPI_TEST_TEST_NACL_IRT_STACK_ALIGNMENT_H_
+#define PPAPI_TEST_TEST_NACL_IRT_STACK_ALIGNMENT_H_
+
+#include <string>
+
+#include "ppapi/c/ppb_var.h"
+#include "ppapi/cpp/var.h"
+#include "ppapi/tests/test_case.h"
+
+class TestNaClIRTStackAlignment : public TestCase {
+ public:
+ explicit TestNaClIRTStackAlignment(TestingInstance* instance)
+ : TestCase(instance) {}
+
+ private:
+ // TestCase implementation.
+ virtual bool Init();
+ virtual void RunTests(const std::string& filter);
+
+ std::string TestMisalignedCallVarAddRef();
+
+ // Used by the tests that access the C API directly.
+ const PPB_Var* var_interface_;
+};
+
+#endif // PPAPI_TEST_TEST_NACL_IRT_STACK_ALIGNMENT_H_