@@ -124,8 +124,23 @@ extern fn stack_exhausted() {
124124 }
125125}
126126
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+
127142#[ 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 ) {
129144 // When the old runtime had segmented stacks, it used a calculation that was
130145 // "limit + RED_ZONE + FUDGE". The red zone was for things like dynamic
131146 // 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) {
138153
139154 return target_record_stack_bounds ( stack_lo, stack_hi) ;
140155
141- #[ cfg( not( windows) ) ] #[ cfg ( not ( target_arch = "x86_64" ) ) ] # [ inline( always) ]
156+ #[ cfg( not( windows) ) ] #[ inline( always) ]
142157 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+ }
143165 #[ cfg( windows, target_arch = "x86_64" ) ] #[ inline( always) ]
144166 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- //
151167 // stack range is at TIB: %gs:0x08 (top) and %gs:0x10 (bottom)
152168 asm ! ( "mov $0, %gs:0x08" :: "r" ( stack_hi) :: "volatile" ) ;
153169 asm ! ( "mov $0, %gs:0x10" :: "r" ( stack_lo) :: "volatile" ) ;
154170 }
155171}
156172
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-
162173/// Records the current limit of the stack as specified by `end`.
163174///
164175/// This is stored in an OS-dependent location, likely inside of the thread
0 commit comments