Howdy Rustaceans,
Recent nightly releases provide an opt-in llvm-tools
rustup component which you can install using
the command: rustup component add llvm-tools
. This component contains the following LLVM tools:
llvm-nm
llvm-objcopy
llvm-objdump
llvm-profdata
llvm-size
Most of these tools are LLVM alternatives to GNU binutils. The main advantage of these LLVM tools
is that they support all the architectures that the Rust compiler supports. For example,
llvm-objdump
con disassemble object files containing machine code for architectures ranging from
ARM Cortex-M (THUMB) all the way to WASM (*) and x86_64. OTOH, if you were to use the GNU tools you
would have to install one set of binutils for each architecture you are working with (e.g.
avr-binutils
, arm-none-eabi-binutils
, msp430-elf-binutils
, etc.).
(*) size
and nm
work fine with WASM but objdump
does not. It could be that disassembly
support is lacking in LLVM 6, the version nightly rustc is currently using, and that upgrading LLVM
would make objdump
work; or it could be something completely different.
How to use these LLVM tools?
After installing the component the LLVM tools will be installed to the rustc sysroot but they will
not be added to your PATH. To use the tools install the cargo-binutils
crate; this crate
provides subcommands that proxy the LLVM tools located in the rustc sysroot:
$ cargo install cargo-binutils
$ cargo new --bin hello && cd $_
$ cargo build --release
$ cargo size -v -- target/release/hello
"/home/japaric/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/bin/llvm-size" "target/release/hello"
text data bss dec hex filename
300887 95276 4288 400451 61c43 target/release/hello
$ cargo objdump -- -d target/release/hello
target/release/hello: file format ELF64-x86-64
Disassembly of section .init:
_init:
5af8: 48 83 ec 08 subq $8, %rsp
5afc: 48 8b 05 d5 14 26 00 movq 2495701(%rip), %rax
5b03: 48 85 c0 testq %rax, %rax
5b06: 74 02 je 2 <_init+0x12>
5b08: ff d0 callq *%rax
5b0a: 48 83 c4 08 addq $8, %rsp
5b0e: c3 retq
Disassembly of section .plt:
(..)
$ # symbols (functions / statics) sorted by size
$ cargo nm -- -print-size -size-sort target/release/hello | tail
000000000002db70 00000000000010d9 t je_arena_palloc
0000000000047920 000000000000184d T je_malloc_vsnprintf
0000000000010b80 0000000000001aa9 t elf_add
0000000000017c10 0000000000001b21 t backtrace_dwarf_add
00000000000313a0 0000000000001b6b t je_arena_boot
0000000000024910 0000000000001eac T mallocx
0000000000041020 0000000000001eed t je_stats_print
000000000001ba70 00000000000022c4 t read_line_info
0000000000015170 0000000000002341 T std::sys_common::backtrace::output::hd4b97ca56fb1f164
0000000000043710 0000000000002617 t stats_arena_print
Check the project README for more details.
Stability
The Rust project provides no guarantee about the availability of these LLVM tools or the stability
of their CLI. On some platforms the llvm-tools
component may be empty, i.e. installing the
component will install nothing.
For these reasons you should not rely on these tools to build code (e.g. in build scripts). Given that these tools are mainly for inspection and profiling the risk of that is very low.
NOTE The rustup component
might be renamed to
llvm-tools-preview
to better reflect the lack of stability guarantees.
Improving the UI
In the first release of cargo-binutils
the Cargo subcommands simply proxy the LLVM tools. In
future releases, we’d like to provide a user interface that feels more integrated with Cargo (e.g.
cargo size --examples
should build all the examples and list their sizes) so we have opened
several issues requesting input on how such UI
should look. If you have thoughts or suggestions on the topic please comment over there!
This change is part of the embedded WG effort towards improving / unifying embedded Rust tooling. See rust-lang-nursery/embedded-wg#50 and rust-lang-nursery/embedded-wg#51.