Skip to content

Commit 39afcd0

Browse files
committed
document this feature in the unstable book
1 parent 3c0907c commit 39afcd0

File tree

1 file changed

+153
-0
lines changed

1 file changed

+153
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
# `emit-stack-sizes`
2+
3+
The tracking issue for this feature is: [#54192]
4+
5+
[#54192]: https://github.com/rust-lang/rust/issues/54192
6+
7+
------------------------
8+
9+
The rustc flag `-Z emit-stack-sizes` makes LLVM emit stack size metadata.
10+
11+
Consider this crate:
12+
13+
```
14+
#![crate_type = "lib"]
15+
16+
use std::ptr;
17+
18+
pub fn foo() {
19+
// this function doesn't use the stack
20+
}
21+
22+
pub fn bar() {
23+
let xs = [0u32; 2];
24+
25+
// force LLVM to allocate `xs` on the stack
26+
unsafe { ptr::read_volatile(&xs.as_ptr()); }
27+
}
28+
```
29+
30+
Using the `-Z emit-stack-sizes` flag produces extra linker sections in the
31+
output *object file*.
32+
33+
``` console
34+
$ rustc -C opt-level=3 --emit=obj foo.rs
35+
36+
$ size -A foo.o
37+
foo.o :
38+
section size addr
39+
.text 0 0
40+
.text._ZN3foo3foo17he211d7b4a3a0c16eE 1 0
41+
.text._ZN3foo3bar17h1acb594305f70c2eE 22 0
42+
.note.GNU-stack 0 0
43+
.eh_frame 72 0
44+
Total 95
45+
46+
$ rustc -C opt-level=3 --emit=obj -Z emit-stack-sizes foo.rs
47+
48+
$ size -A foo.o
49+
foo.o :
50+
section size addr
51+
.text 0 0
52+
.text._ZN3foo3foo17he211d7b4a3a0c16eE 1 0
53+
.stack_sizes 9 0
54+
.text._ZN3foo3bar17h1acb594305f70c2eE 22 0
55+
.stack_sizes 9 0
56+
.note.GNU-stack 0 0
57+
.eh_frame 72 0
58+
Total 113
59+
```
60+
61+
As of LLVM 7.0 the data will be written into a section named `.stack_sizes` and
62+
the format is "an array of pairs of function symbol values (pointer size) and
63+
stack sizes (unsigned LEB128)".
64+
65+
``` console
66+
$ objdump -d foo.o
67+
68+
foo.o: file format elf64-x86-64
69+
70+
Disassembly of section .text._ZN3foo3foo17he211d7b4a3a0c16eE:
71+
72+
0000000000000000 <_ZN3foo3foo17he211d7b4a3a0c16eE>:
73+
0: c3 retq
74+
75+
Disassembly of section .text._ZN3foo3bar17h1acb594305f70c2eE:
76+
77+
0000000000000000 <_ZN3foo3bar17h1acb594305f70c2eE>:
78+
0: 48 83 ec 10 sub $0x10,%rsp
79+
4: 48 8d 44 24 08 lea 0x8(%rsp),%rax
80+
9: 48 89 04 24 mov %rax,(%rsp)
81+
d: 48 8b 04 24 mov (%rsp),%rax
82+
11: 48 83 c4 10 add $0x10,%rsp
83+
15: c3 retq
84+
85+
$ objdump -s -j .stack_sizes foo.o
86+
87+
foo.o: file format elf64-x86-64
88+
89+
Contents of section .stack_sizes:
90+
0000 00000000 00000000 00 .........
91+
Contents of section .stack_sizes:
92+
0000 00000000 00000000 10 .........
93+
```
94+
95+
It's important to note that linkers will discard this linker section by default.
96+
To preserve the section you can use a linker script like the one shown below.
97+
98+
``` text
99+
/* file: keep-stack-sizes.x */
100+
SECTIONS
101+
{
102+
.stack_sizes :
103+
{
104+
KEEP(*(.stack_sizes));
105+
}
106+
}
107+
```
108+
109+
The linker script must be passed to the linker using a rustc flag like `-C
110+
link-arg`.
111+
112+
```
113+
// file: src/main.rs
114+
use std::ptr;
115+
116+
#[inline(never)]
117+
fn main() {
118+
let xs = [0u32; 2];
119+
120+
// force LLVM to allocate `xs` on the stack
121+
unsafe { ptr::read_volatile(&xs.as_ptr()); }
122+
}
123+
```
124+
125+
``` console
126+
$ RUSTFLAGS="-Z emit-stack-sizes" cargo build --release
127+
128+
$ size -A target/release/hello | grep stack_sizes || echo section was not found
129+
section was not found
130+
131+
$ RUSTFLAGS="-Z emit-stack-sizes" cargo rustc --release -- \
132+
-C link-arg=-Wl,-Tkeep-stack-sizes.x \
133+
-C link-arg=-N
134+
135+
$ size -A target/release/hello | grep stack_sizes
136+
.stack_sizes 90 205368
137+
138+
$ objdump -s -j .stack_sizes target/release/hello
139+
140+
target/release/hello: file format elf64-x86-64
141+
142+
Contents of section .stack_sizes:
143+
32238 c0040000 00000000 08f00400 00000000 ................
144+
32248 00080005 00000000 00000810 05000000 ................
145+
32258 00000000 20050000 00000000 10400500 .... ........@..
146+
32268 00000000 00087005 00000000 00000080 ......p.........
147+
32278 05000000 00000000 90050000 00000000 ................
148+
32288 00a00500 00000000 0000 ..........
149+
```
150+
151+
> Author note: I'm not entirely sure why, in *this* case, `-N` is required in
152+
> addition to `-Tkeep-stack-sizes.x`. For example, it's not required when
153+
> producing statically linked files for the ARM Cortex-M architecture.

0 commit comments

Comments
 (0)