@@ -124,8 +124,23 @@ extern fn stack_exhausted() {
124
124
}
125
125
}
126
126
127
+ // Windows maintains a record of upper and lower stack bounds in the Thread Information
128
+ // Block (TIB), and some syscalls do check that addresses which are supposed to be in
129
+ // the stack, indeed lie between these two values.
130
+ // (See https://github.com/rust-lang/rust/issues/3445#issuecomment-26114839)
131
+ //
132
+ // When using Rust-managed stacks (libgreen), we must maintain these values accordingly.
133
+ // For OS-managed stacks (libnative), we let the OS manage them for us.
134
+ //
135
+ // On all other platforms both variants behave identically.
136
+
137
+ #[ inline( always) ]
138
+ pub unsafe fn record_os_managed_stack_bounds ( stack_lo : uint , _stack_hi : uint ) {
139
+ record_sp_limit ( stack_lo + RED_ZONE ) ;
140
+ }
141
+
127
142
#[ inline( always) ]
128
- pub unsafe fn record_stack_bounds_green ( stack_lo : uint , stack_hi : uint ) {
143
+ pub unsafe fn record_rust_managed_stack_bounds ( stack_lo : uint , stack_hi : uint ) {
129
144
// When the old runtime had segmented stacks, it used a calculation that was
130
145
// "limit + RED_ZONE + FUDGE". The red zone was for things like dynamic
131
146
// symbol resolution, llvm function calls, etc. In theory this red zone
@@ -138,27 +153,23 @@ pub unsafe fn record_stack_bounds_green(stack_lo: uint, stack_hi: uint) {
138
153
139
154
return target_record_stack_bounds ( stack_lo, stack_hi) ;
140
155
141
- #[ cfg( not( windows) ) ] #[ cfg ( not ( target_arch = "x86_64" ) ) ] # [ inline( always) ]
156
+ #[ cfg( not( windows) ) ] #[ inline( always) ]
142
157
unsafe fn target_record_stack_bounds ( _stack_lo : uint , _stack_hi : uint ) { }
158
+
159
+ #[ cfg( windows, target_arch = "x86" ) ] #[ inline( always) ]
160
+ unsafe fn target_record_stack_bounds ( stack_lo : uint , stack_hi : uint ) {
161
+ // stack range is at TIB: %fs:0x04 (top) and %fs:0x08 (bottom)
162
+ asm ! ( "mov $0, %fs:0x04" :: "r" ( stack_hi) :: "volatile" ) ;
163
+ asm ! ( "mov $0, %fs:0x08" :: "r" ( stack_lo) :: "volatile" ) ;
164
+ }
143
165
#[ cfg( windows, target_arch = "x86_64" ) ] #[ inline( always) ]
144
166
unsafe fn target_record_stack_bounds ( stack_lo : uint , stack_hi : uint ) {
145
- // Windows compiles C functions which may check the stack bounds. This
146
- // means that if we want to perform valid FFI on windows, then we need
147
- // to ensure that the stack bounds are what they truly are for this
148
- // task. More info can be found at:
149
- // https://github.com/rust-lang/rust/issues/3445#issuecomment-26114839
150
- //
151
167
// stack range is at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
152
168
asm ! ( "mov $0, %gs:0x08" :: "r" ( stack_hi) :: "volatile" ) ;
153
169
asm ! ( "mov $0, %gs:0x10" :: "r" ( stack_lo) :: "volatile" ) ;
154
170
}
155
171
}
156
172
157
- #[ inline( always) ]
158
- pub unsafe fn record_stack_bounds ( stack_lo : uint , _stack_hi : uint ) {
159
- record_sp_limit ( stack_lo + RED_ZONE ) ;
160
- }
161
-
162
173
/// Records the current limit of the stack as specified by `end`.
163
174
///
164
175
/// This is stored in an OS-dependent location, likely inside of the thread
0 commit comments