]> git.lizzy.rs Git - rust.git/blob - src/doc/unstable-book/src/used.md
Rollup merge of #41135 - japaric:unstable-docs, r=steveklabnik
[rust.git] / src / doc / unstable-book / src / used.md
1 # `used`
2
3 The tracking issue for this feature
4 is: [40289](https://github.com/rust-lang/rust/issues/40289).
5
6 ------------------------
7
8 The `#[used]` attribute can be applied to `static` variables to prevent the Rust
9 compiler from optimizing them away even if they appear to be unused by the crate
10 (appear to be "dead code").
11
12 ``` rust
13 #![feature(used)]
14
15 #[used]
16 static FOO: i32 = 1;
17
18 static BAR: i32 = 2;
19
20 fn main() {}
21 ```
22
23 If you compile this program into an object file, you'll see that `FOO` makes it
24 to the object file but `BAR` doesn't. Neither static variable is used by the
25 program.
26
27 ``` text
28 $ rustc -C opt-level=3 --emit=obj used.rs
29
30 $ nm -C used.o
31 0000000000000000 T main
32                  U std::rt::lang_start
33 0000000000000000 r used::FOO
34 0000000000000000 t used::main
35 ```
36
37 Note that the *linker* knows nothing about the `#[used]` attribute and will
38 remove `#[used]` symbols if they are not referenced by other parts of the
39 program:
40
41 ``` text
42 $ rustc -C opt-level=3 used.rs
43
44 $ nm -C used | grep FOO
45 ```
46
47 "This doesn't sound too useful then!" you may think but keep reading.
48
49 To preserve the symbols all the way to the final binary, you'll need the
50 cooperation of the linker. Here's one example:
51
52 The ELF standard defines two special sections, `.init_array` and
53 `.pre_init_array`, that may contain function pointers which will be executed
54 *before* the `main` function is invoked. The linker will preserve symbols placed
55 in these sections (at least when linking programs that target the `*-*-linux-*`
56 targets).
57
58 ``` rust,ignore
59 #![feature(used)]
60
61 extern "C" fn before_main() {
62     println!("Hello, world!");
63 }
64
65 #[link_section = ".init_array"]
66 #[used]
67 static INIT_ARRAY: [extern "C" fn(); 1] = [before_main];
68
69 fn main() {}
70 ```
71
72 So, `#[used]` and `#[link_section]` can be combined to obtain "life before
73 main".
74
75 ``` text
76 $ rustc -C opt-level=3 before-main.rs
77
78 $ ./before-main
79 Hello, world!
80 ```
81
82 Another example: ARM Cortex-M microcontrollers need their reset handler, a
83 pointer to the function that will executed right after the microcontroller is
84 turned on, to be placed near the start of their FLASH memory to boot properly.
85
86 This condition can be met using `#[used]` and `#[link_section]` plus a linker
87 script.
88
89 ``` rust,ignore
90 #![feature(lang_items)]
91 #![feature(used)]
92 #![no_main]
93 #![no_std]
94
95 extern "C" fn reset_handler() -> ! {
96     loop {}
97 }
98
99 #[link_section = ".reset_handler"]
100 #[used]
101 static RESET_HANDLER: extern "C" fn() -> ! = reset_handler;
102
103 #[lang = "panic_fmt"]
104 fn panic_fmt() {}
105 ```
106
107 ``` text
108 MEMORY
109 {
110   FLASH : ORIGIN = 0x08000000, LENGTH = 128K
111   RAM : ORIGIN = 0x20000000, LENGTH = 20K
112 }
113
114 SECTIONS
115 {
116   .text ORIGIN(FLASH) :
117   {
118     /* Vector table */
119     LONG(ORIGIN(RAM) + LENGTH(RAM)); /* initial SP value */
120     KEEP(*(.reset_handler));
121
122     /* Omitted: The rest of the vector table */
123
124     *(.text.*);
125   } > FLASH
126
127   /DISCARD/ :
128   {
129     /* Unused unwinding stuff */
130     *(.ARM.exidx.*)
131   }
132 }
133 ```
134
135 ``` text
136 $ xargo rustc --target thumbv7m-none-eabi --release -- \
137     -C link-arg=-Tlink.x -C link-arg=-nostartfiles
138
139 $ arm-none-eabi-objdump -Cd target/thumbv7m-none-eabi/release/app
140 ./target/thumbv7m-none-eabi/release/app:     file format elf32-littlearm
141
142
143 Disassembly of section .text:
144
145 08000000 <app::RESET_HANDLER-0x4>:
146  8000000:       20005000        .word   0x20005000
147
148 08000004 <app::RESET_HANDLER>:
149  8000004:       08000009                                ....
150
151 08000008 <app::reset_handler>:
152  8000008:       e7fe            b.n     8000008 <app::reset_handler>
153 ```