]> git.proxmox.com Git - rustc.git/blame - src/libstd/sys/unix/stack_overflow.rs
Imported Upstream version 1.3.0+dfsg1
[rustc.git] / src / libstd / sys / unix / stack_overflow.rs
CommitLineData
1a4d82fc
JJ
1// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11use libc;
12use core::prelude::*;
13use self::imp::{make_handler, drop_handler};
14
15pub use self::imp::{init, cleanup};
16
17pub struct Handler {
18 _data: *mut libc::c_void
19}
20
21impl Handler {
22 pub unsafe fn new() -> Handler {
23 make_handler()
24 }
25}
26
27impl Drop for Handler {
28 fn drop(&mut self) {
29 unsafe {
30 drop_handler(self);
31 }
32 }
33}
34
85aaf69f
SL
35#[cfg(any(target_os = "linux",
36 target_os = "macos",
c34b1796 37 target_os = "bitrig",
c1a9b12d 38 target_os = "netbsd",
85aaf69f 39 target_os = "openbsd"))]
1a4d82fc 40mod imp {
1a4d82fc
JJ
41 use sys_common::stack;
42
43 use super::Handler;
44 use rt::util::report_overflow;
45 use mem;
46 use ptr;
47 use intrinsics;
62682a34
SL
48 use sys::c::{siginfo, sigaction, SIGBUS, SIG_DFL,
49 SA_SIGINFO, SA_ONSTACK, sigaltstack,
50 SIGSTKSZ, sighandler_t, raise};
1a4d82fc
JJ
51 use libc;
52 use libc::funcs::posix88::mman::{mmap, munmap};
62682a34 53 use libc::funcs::posix01::signal::signal;
1a4d82fc
JJ
54 use libc::consts::os::posix88::{SIGSEGV,
55 PROT_READ,
56 PROT_WRITE,
57 MAP_PRIVATE,
58 MAP_ANON,
59 MAP_FAILED};
60
61 use sys_common::thread_info;
62
63
64 // This is initialized in init() and only read from after
c34b1796 65 static mut PAGE_SIZE: usize = 0;
1a4d82fc
JJ
66
67 #[no_stack_check]
68 unsafe extern fn signal_handler(signum: libc::c_int,
69 info: *mut siginfo,
70 _data: *mut libc::c_void) {
71
72 // We can not return from a SIGSEGV or SIGBUS signal.
73 // See: https://www.gnu.org/software/libc/manual/html_node/Handler-Returns.html
74
75 unsafe fn term(signum: libc::c_int) -> ! {
76 use core::mem::transmute;
77
78 signal(signum, transmute(SIG_DFL));
79 raise(signum);
80 intrinsics::abort();
81 }
82
83 // We're calling into functions with stack checks
84 stack::record_sp_limit(0);
85
d9579d0f 86 let guard = thread_info::stack_guard().unwrap_or(0);
c34b1796 87 let addr = (*info).si_addr as usize;
1a4d82fc
JJ
88
89 if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard {
90 term(signum);
91 }
92
93 report_overflow();
94
95 intrinsics::abort()
96 }
97
98 static mut MAIN_ALTSTACK: *mut libc::c_void = 0 as *mut libc::c_void;
99
100 pub unsafe fn init() {
101 let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
102 if psize == -1 {
103 panic!("failed to get page size");
104 }
105
c34b1796 106 PAGE_SIZE = psize as usize;
1a4d82fc
JJ
107
108 let mut action: sigaction = mem::zeroed();
109 action.sa_flags = SA_SIGINFO | SA_ONSTACK;
110 action.sa_sigaction = signal_handler as sighandler_t;
111 sigaction(SIGSEGV, &action, ptr::null_mut());
112 sigaction(SIGBUS, &action, ptr::null_mut());
113
114 let handler = make_handler();
115 MAIN_ALTSTACK = handler._data;
116 mem::forget(handler);
117 }
118
119 pub unsafe fn cleanup() {
120 Handler { _data: MAIN_ALTSTACK };
121 }
122
123 pub unsafe fn make_handler() -> Handler {
124 let alt_stack = mmap(ptr::null_mut(),
62682a34 125 SIGSTKSZ,
1a4d82fc
JJ
126 PROT_READ | PROT_WRITE,
127 MAP_PRIVATE | MAP_ANON,
128 -1,
129 0);
130 if alt_stack == MAP_FAILED {
131 panic!("failed to allocate an alternative stack");
132 }
133
134 let mut stack: sigaltstack = mem::zeroed();
135
136 stack.ss_sp = alt_stack;
137 stack.ss_flags = 0;
138 stack.ss_size = SIGSTKSZ;
139
140 sigaltstack(&stack, ptr::null_mut());
141
142 Handler { _data: alt_stack }
143 }
144
145 pub unsafe fn drop_handler(handler: &mut Handler) {
146 munmap(handler._data, SIGSTKSZ);
147 }
1a4d82fc
JJ
148}
149
150#[cfg(not(any(target_os = "linux",
85aaf69f 151 target_os = "macos",
c34b1796 152 target_os = "bitrig",
c1a9b12d 153 target_os = "netbsd",
85aaf69f 154 target_os = "openbsd")))]
1a4d82fc
JJ
155mod imp {
156 use libc;
157
158 pub unsafe fn init() {
159 }
160
161 pub unsafe fn cleanup() {
162 }
163
164 pub unsafe fn make_handler() -> super::Handler {
85aaf69f 165 super::Handler { _data: 0 as *mut libc::c_void }
1a4d82fc
JJ
166 }
167
168 pub unsafe fn drop_handler(_handler: &mut super::Handler) {
169 }
170}