about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBrian Anderson <banderson@mozilla.com>2011-12-15 00:24:35 -0800
committerBrian Anderson <banderson@mozilla.com>2011-12-16 18:18:43 -0800
commit121c4201844c1bec4a8f2a4450e4b9330ee9bf28 (patch)
tree54b9576ba501dc5de392ad5a1a49d4ff11cd9c63
parent4f826b34cbb101f2bfe2660f5c4f8db6d044f83a (diff)
downloadrust-121c4201844c1bec4a8f2a4450e4b9330ee9bf28.tar.gz
rust-121c4201844c1bec4a8f2a4450e4b9330ee9bf28.zip
rt: Insert stack alignment checks into upcalls
-rw-r--r--src/rt/arch/i386/record_sp.S12
-rw-r--r--src/rt/arch/x86_64/record_sp.S10
-rw-r--r--src/rt/rust_upcall.cpp10
3 files changed, 31 insertions, 1 deletions
diff --git a/src/rt/arch/i386/record_sp.S b/src/rt/arch/i386/record_sp.S
index 0c9f0782846..b9c42a650d8 100644
--- a/src/rt/arch/i386/record_sp.S
+++ b/src/rt/arch/i386/record_sp.S
@@ -3,13 +3,16 @@
 #if defined(__APPLE__) || defined(_WIN32)
 #define RECORD_SP          _record_sp
 #define GET_SP             _get_sp
+#define CHECK_STACK        _check_stack_alignment
 #else
 #define RECORD_SP          record_sp
 #define GET_SP             get_sp
+#define CHECK_STACK        check_stack_alignment
 #endif
 
 .globl RECORD_SP
 .globl GET_SP
+.globl CHECK_STACK
 
 #if defined(__linux__)
 RECORD_SP:
@@ -35,4 +38,11 @@ RECORD_SP:
 
 GET_SP:
 	movl %esp, %eax
-	ret
\ No newline at end of file
+	ret
+
+// This will segfault if not called on a 16-byte boundary
+CHECK_STACK:
+	subl $28, %esp
+	movaps %xmm0, (%esp)
+	addl $28, %esp
+	ret
diff --git a/src/rt/arch/x86_64/record_sp.S b/src/rt/arch/x86_64/record_sp.S
index 415f6685655..af217d0f37f 100644
--- a/src/rt/arch/x86_64/record_sp.S
+++ b/src/rt/arch/x86_64/record_sp.S
@@ -3,13 +3,16 @@
 #if defined(__APPLE__) || defined(_WIN32)
 #define RECORD_SP          _record_sp
 #define GET_SP             _get_sp
+#define CHECK_STACK        _check_stack_alignment
 #else
 #define RECORD_SP          record_sp
 #define GET_SP             get_sp
+#define CHECK_STACK        check_stack_alignment
 #endif
 
 .globl RECORD_SP
 .globl GET_SP
+.globl CHECK_STACK
 
 #if defined(__linux__)
 RECORD_SP:
@@ -30,3 +33,10 @@ RECORD_SP:
 GET_SP:
 	movq %rsp, %rax
 	ret
+
+// This will segfault if not called on a 16-byte boundary
+CHECK_STACK:
+	subq $24, %rsp
+	movaps %xmm0, (%rsp)
+	addq $24, %rsp
+	ret
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp
index 97e1321c02d..dd7e275cd04 100644
--- a/src/rt/rust_upcall.cpp
+++ b/src/rt/rust_upcall.cpp
@@ -14,6 +14,14 @@
 #include "rust_upcall.h"
 #include <stdint.h>
 
+
+// This is called to ensure we've set up our rust stacks
+// correctly. Strategically placed at entry to upcalls because they begin on
+// the rust stack and happen frequently enough to catch most stack changes,
+// including at the beginning of all landing pads.
+extern "C" void
+check_stack_alignment() __attribute__ ((aligned (16)));
+
 #define SWITCH_STACK(A, F) upcall_call_shim_on_c_stack((void*)A, (void*)F)
 
 extern "C" void record_sp(void *limit);
@@ -26,6 +34,7 @@ extern "C" void record_sp(void *limit);
  */
 extern "C" CDECL void
 upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
+    check_stack_alignment();
     rust_task *task = rust_scheduler::get_task();
 
     // FIXME (1226) - The shim functions generated by rustc contain the
@@ -594,6 +603,7 @@ upcall_del_stack() {
 // needs to acquire the value of the stack pointer
 extern "C" CDECL void
 upcall_reset_stack_limit() {
+    check_stack_alignment();
     rust_task *task = rust_scheduler::get_task();
     task->reset_stack_limit();
 }