3 The tracking issue for this feature is: [#54192]
5 [#54192]: https://github.com/rust-lang/rust/issues/54192
7 ------------------------
9 The rustc flag `-Z emit-stack-sizes` makes LLVM emit stack size metadata.
11 > **NOTE**: This LLVM feature only supports the ELF object format as of LLVM
12 > 8.0. Using this flag with targets that use other object formats (e.g. macOS
13 > and Windows) will result in it being ignored.
18 #![crate_type = "lib"]
23 // this function doesn't use the stack
29 // force LLVM to allocate `xs` on the stack
30 unsafe { ptr::read_volatile(&xs.as_ptr()); }
34 Using the `-Z emit-stack-sizes` flag produces extra linker sections in the
38 $ rustc -C opt-level=3 --emit=obj foo.rs
44 .text._ZN3foo3foo17he211d7b4a3a0c16eE 1 0
45 .text._ZN3foo3bar17h1acb594305f70c2eE 22 0
50 $ rustc -C opt-level=3 --emit=obj -Z emit-stack-sizes foo.rs
56 .text._ZN3foo3foo17he211d7b4a3a0c16eE 1 0
58 .text._ZN3foo3bar17h1acb594305f70c2eE 22 0
65 As of LLVM 7.0 the data will be written into a section named `.stack_sizes` and
66 the format is "an array of pairs of function symbol values (pointer size) and
67 stack sizes (unsigned LEB128)".
72 foo.o: file format elf64-x86-64
74 Disassembly of section .text._ZN3foo3foo17he211d7b4a3a0c16eE:
76 0000000000000000 <_ZN3foo3foo17he211d7b4a3a0c16eE>:
79 Disassembly of section .text._ZN3foo3bar17h1acb594305f70c2eE:
81 0000000000000000 <_ZN3foo3bar17h1acb594305f70c2eE>:
82 0: 48 83 ec 10 sub $0x10,%rsp
83 4: 48 8d 44 24 08 lea 0x8(%rsp),%rax
84 9: 48 89 04 24 mov %rax,(%rsp)
85 d: 48 8b 04 24 mov (%rsp),%rax
86 11: 48 83 c4 10 add $0x10,%rsp
89 $ objdump -s -j .stack_sizes foo.o
91 foo.o: file format elf64-x86-64
93 Contents of section .stack_sizes:
94 0000 00000000 00000000 00 .........
95 Contents of section .stack_sizes:
96 0000 00000000 00000000 10 .........
99 It's important to note that linkers will discard this linker section by default.
100 To preserve the section you can use a linker script like the one shown below.
103 /* file: keep-stack-sizes.x */
106 /* `INFO` makes the section not allocatable so it won't be loaded into memory */
107 .stack_sizes (INFO) :
109 KEEP(*(.stack_sizes));
114 The linker script must be passed to the linker using a rustc flag like `-C
125 // force LLVM to allocate `xs` on the stack
126 unsafe { ptr::read_volatile(&xs.as_ptr()); }
131 $ RUSTFLAGS="-Z emit-stack-sizes" cargo build --release
133 $ size -A target/release/hello | grep stack_sizes || echo section was not found
134 section was not found
136 $ RUSTFLAGS="-Z emit-stack-sizes" cargo rustc --release -- \
137 -C link-arg=-Wl,-Tkeep-stack-sizes.x \
140 $ size -A target/release/hello | grep stack_sizes
141 .stack_sizes 90 176272
143 $ # non-allocatable section (flags don't contain the "A" (alloc) flag)
144 $ readelf -S target/release/hello
146 [Nr] Name Type Address Offset
147 Size EntSize Flags Link Info Align
149 [1031] .stack_sizes PROGBITS 000000000002b090 0002b0f0
150 000000000000005a 0000000000000000 L 5 0 1
152 $ objdump -s -j .stack_sizes target/release/hello
154 target/release/hello: file format elf64-x86-64
156 Contents of section .stack_sizes:
157 2b090 c0040000 00000000 08f00400 00000000 ................
158 2b0a0 00080005 00000000 00000810 05000000 ................
159 2b0b0 00000000 20050000 00000000 10400500 .... ........@..
160 2b0c0 00000000 00087005 00000000 00000080 ......p.........
161 2b0d0 05000000 00000000 90050000 00000000 ................
162 2b0e0 00a00500 00000000 0000 ..........
165 > Author note: I'm not entirely sure why, in *this* case, `-N` is required in
166 > addition to `-Tkeep-stack-sizes.x`. For example, it's not required when
167 > producing statically linked files for the ARM Cortex-M architecture.