Skip to content

Commit 4d9df62

Browse files
committed
Auto merge of #194 - mattico:i386, r=alexcrichton
Implement x86 chkstk in "rust" cc #183 Basically the same as the x86_64 ones, except `__alloca` doesn't need to fix the parameter register. I've manually verified that the disassembly is the same, and that these work in a compiled rust program. The second commit disables compiling probestack functions for `feature = mangled-names`. They aren't needed during testing because they aren't comparison tested and the unmangled versions are the ones that actually get used. r? @alexcrichton
2 parents a767bab + a40cc6a commit 4d9df62

File tree

6 files changed

+124
-50
lines changed

6 files changed

+124
-50
lines changed

README.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,8 @@ features = ["c"]
159159
- [x] floatunsisf.c
160160
- [ ] i386/ashldi3.S
161161
- [ ] i386/ashrdi3.S
162-
- [ ] i386/chkstk.S
163-
- [ ] i386/chkstk2.S
162+
- [x] i386/chkstk.S
163+
- [x] i386/chkstk2.S
164164
- [ ] i386/divdi3.S
165165
- [ ] i386/lshrdi3.S
166166
- [ ] i386/moddi3.S

build.rs

-2
Original file line numberDiff line numberDiff line change
@@ -4176,8 +4176,6 @@ mod c {
41764176
&[
41774177
"i386/ashldi3.S",
41784178
"i386/ashrdi3.S",
4179-
"i386/chkstk.S",
4180-
"i386/chkstk2.S",
41814179
"i386/divdi3.S",
41824180
"i386/floatdidf.S",
41834181
"i386/floatdisf.S",

src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ pub mod mem;
5151
#[cfg(target_arch = "arm")]
5252
pub mod arm;
5353

54+
#[cfg(target_arch = "x86")]
55+
pub mod x86;
56+
5457
#[cfg(target_arch = "x86_64")]
5558
pub mod x86_64;
5659

src/probestack.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@
4444
#![cfg(not(windows))] // Windows already has builtins to do this
4545

4646
#[naked]
47-
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
48-
#[cfg(target_arch = "x86_64")]
47+
#[no_mangle]
48+
#[cfg(all(target_arch = "x86_64", not(feature = "mangled-names")))]
4949
pub unsafe extern fn __rust_probestack() {
5050
// Our goal here is to touch each page between %rsp+8 and %rsp+8-%rax,
5151
// ensuring that if any pages are unmapped we'll make a page fault.
@@ -87,8 +87,8 @@ pub unsafe extern fn __rust_probestack() {
8787
}
8888

8989
#[naked]
90-
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
91-
#[cfg(target_arch = "x86")]
90+
#[no_mangle]
91+
#[cfg(all(target_arch = "x86", not(feature = "mangled-names")))]
9292
pub unsafe extern fn __rust_probestack() {
9393
// This is the same as x86_64 above, only translated for 32-bit sizes. Note
9494
// that on Unix we're expected to restore everything as it was, this

src/x86.rs

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
#![allow(unused_imports)]
2+
3+
use core::intrinsics;
4+
5+
// NOTE These functions are implemented using assembly because they using a custom
6+
// calling convention which can't be implemented using a normal Rust function
7+
8+
// NOTE These functions are never mangled as they are not tested against compiler-rt
9+
// and mangling ___chkstk would break the `jmp ___chkstk` instruction in __alloca
10+
11+
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
12+
#[naked]
13+
#[no_mangle]
14+
pub unsafe fn ___chkstk_ms() {
15+
asm!("
16+
push %ecx
17+
push %eax
18+
cmp $$0x1000,%eax
19+
lea 12(%esp),%ecx
20+
jb 1f
21+
2:
22+
sub $$0x1000,%ecx
23+
test %ecx,(%ecx)
24+
sub $$0x1000,%eax
25+
cmp $$0x1000,%eax
26+
ja 2b
27+
1:
28+
sub %eax,%ecx
29+
test %ecx,(%ecx)
30+
pop %eax
31+
pop %ecx
32+
ret");
33+
intrinsics::unreachable();
34+
}
35+
36+
// FIXME: __alloca should be an alias to __chkstk
37+
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
38+
#[naked]
39+
#[no_mangle]
40+
pub unsafe fn __alloca() {
41+
asm!("jmp ___chkstk // Jump to ___chkstk since fallthrough may be unreliable");
42+
intrinsics::unreachable();
43+
}
44+
45+
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
46+
#[naked]
47+
#[no_mangle]
48+
pub unsafe fn ___chkstk() {
49+
asm!("
50+
push %ecx
51+
cmp $$0x1000,%eax
52+
lea 8(%esp),%ecx // esp before calling this routine -> ecx
53+
jb 1f
54+
2:
55+
sub $$0x1000,%ecx
56+
test %ecx,(%ecx)
57+
sub $$0x1000,%eax
58+
cmp $$0x1000,%eax
59+
ja 2b
60+
1:
61+
sub %eax,%ecx
62+
test %ecx,(%ecx)
63+
64+
lea 4(%esp),%eax // load pointer to the return address into eax
65+
mov %ecx,%esp // install the new top of stack pointer into esp
66+
mov -4(%eax),%ecx // restore ecx
67+
push (%eax) // push return address onto the stack
68+
sub %esp,%eax // restore the original value in eax
69+
ret");
70+
intrinsics::unreachable();
71+
}

src/x86_64.rs

+44-42
Original file line numberDiff line numberDiff line change
@@ -8,62 +8,64 @@ use core::intrinsics;
88
// NOTE These functions are never mangled as they are not tested against compiler-rt
99
// and mangling ___chkstk would break the `jmp ___chkstk` instruction in __alloca
1010

11-
#[cfg(all(windows, target_env = "gnu"))]
11+
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
1212
#[naked]
13-
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
13+
#[no_mangle]
1414
pub unsafe fn ___chkstk_ms() {
15-
asm!("push %rcx
16-
push %rax
17-
cmp $$0x1000,%rax
18-
lea 24(%rsp),%rcx
19-
jb 1f
20-
2:
21-
sub $$0x1000,%rcx
22-
test %rcx,(%rcx)
23-
sub $$0x1000,%rax
24-
cmp $$0x1000,%rax
25-
ja 2b
26-
1:
27-
sub %rax,%rcx
28-
test %rcx,(%rcx)
29-
pop %rax
30-
pop %rcx
31-
ret");
15+
asm!("
16+
push %rcx
17+
push %rax
18+
cmp $$0x1000,%rax
19+
lea 24(%rsp),%rcx
20+
jb 1f
21+
2:
22+
sub $$0x1000,%rcx
23+
test %rcx,(%rcx)
24+
sub $$0x1000,%rax
25+
cmp $$0x1000,%rax
26+
ja 2b
27+
1:
28+
sub %rax,%rcx
29+
test %rcx,(%rcx)
30+
pop %rax
31+
pop %rcx
32+
ret");
3233
intrinsics::unreachable();
3334
}
3435

35-
#[cfg(all(windows, target_env = "gnu"))]
36+
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
3637
#[naked]
37-
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
38+
#[no_mangle]
3839
pub unsafe fn __alloca() {
3940
asm!("mov %rcx,%rax // x64 _alloca is a normal function with parameter in rcx
4041
jmp ___chkstk // Jump to ___chkstk since fallthrough may be unreliable");
4142
intrinsics::unreachable();
4243
}
4344

44-
#[cfg(all(windows, target_env = "gnu"))]
45+
#[cfg(all(windows, target_env = "gnu", not(feature = "mangled-names")))]
4546
#[naked]
46-
#[cfg_attr(not(feature = "mangled-names"), no_mangle)]
47+
#[no_mangle]
4748
pub unsafe fn ___chkstk() {
48-
asm!("push %rcx
49-
cmp $$0x1000,%rax
50-
lea 16(%rsp),%rcx // rsp before calling this routine -> rcx
51-
jb 1f
52-
2:
53-
sub $$0x1000,%rcx
54-
test %rcx,(%rcx)
55-
sub $$0x1000,%rax
56-
cmp $$0x1000,%rax
57-
ja 2b
58-
1:
59-
sub %rax,%rcx
60-
test %rcx,(%rcx)
49+
asm!("
50+
push %rcx
51+
cmp $$0x1000,%rax
52+
lea 16(%rsp),%rcx // rsp before calling this routine -> rcx
53+
jb 1f
54+
2:
55+
sub $$0x1000,%rcx
56+
test %rcx,(%rcx)
57+
sub $$0x1000,%rax
58+
cmp $$0x1000,%rax
59+
ja 2b
60+
1:
61+
sub %rax,%rcx
62+
test %rcx,(%rcx)
6163
62-
lea 8(%rsp),%rax // load pointer to the return address into rax
63-
mov %rcx,%rsp // install the new top of stack pointer into rsp
64-
mov -8(%rax),%rcx // restore rcx
65-
push (%rax) // push return address onto the stack
66-
sub %rsp,%rax // restore the original value in rax
67-
ret");
64+
lea 8(%rsp),%rax // load pointer to the return address into rax
65+
mov %rcx,%rsp // install the new top of stack pointer into rsp
66+
mov -8(%rax),%rcx // restore rcx
67+
push (%rax) // push return address onto the stack
68+
sub %rsp,%rax // restore the original value in rax
69+
ret");
6870
intrinsics::unreachable();
6971
}

0 commit comments

Comments
 (0)