`llvm-tools`, a new rustup component for binary inspection (objdump, nm, size) and profiling (profdata)


#1

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.


The Embedded Working Group Newsletter - 6
#2

Thanks! Maybe include llvm-strip as well?


#3

Actually the GNU binutils can be built with --enable-targets=all, in which case they will function this way. It’s only GCC that bakes in a single back end.


#4

Sounds reasonable to me. You can send a PR; I believe you would only need to add the name of the tool to this list along with the rationale for including it.


#5

Yes, but most Linux distros don’t use that option to build the binutils packages; instead they provide several binutils packages – one for each architecture.

Building binutils yourself is more troublesome than running apt-get several times and rustup component add is much simpler than both alternatives.


#6

Since you’re talking about apt-get, Debian and Ubuntu both have a binutils-multiarch package.


#7

would it be possible to add llc as well?