nnnmmm
nnnmmm

Reputation: 8754

How do I find the assembly code for my function in a (release) Rust build?

Compiler Explorer seems to be able to reliably find the assembly code corresponding to a function. How can I do that myself, assuming a x86_64-unknown-linux-gnu toolchain, a regular (no attributes) function, and without extra tools like cargo-asm?

I know that to produce the assembly, I can use rustc's --emit asm flag. One might think that finding the function is easy as searching for its name in the .s file, but I found that it's not.

For instance, the .s file often doesn't even mention the function name, in which case adding #[inline(never)] to the function helps. Second, having found the label with the function name, how do you determine where the function ends? In my test crate, I found a second mention of the function name in a .size directive farther down – does that maybe mark the end of the function? Or is it maybe the first retq after the function start?

Assuming this goal is achievable, I hope to learn:

Upvotes: 2

Views: 2699

Answers (1)

nnnmmm
nnnmmm

Reputation: 8754

Since there was no answer, I did a little bit of research and this should do the trick:

  1. Make sure the function is used by main() in case of a binary crate, or by a pub function in case of a library crate (or is pub itself).
  2. To avoid the compiler inlining your benchmark, mark it #[inline(never)]
  3. Search for the function name, which should find the start, which looks like this:
    .type   <mangled_name>,@function
<mangled_name>:
    .cfi_startproc
  1. Search for the end of the function, which is marked by:
.Lfunc_end<number>:
    .size   <mangled_name>, .Lfunc_end<number>-<mangled_name>
    .cfi_endproc

This can sometimes be preceded by a retq, but not reliably.

Those lines that start with a dot and do not end with a colon, like .type, are directives. The directives that the GNU assembler understands are documented here, and the output of --emit asm should be valid input to the GNU assembler.

Compiler Explorer and cargo-asm

It seems that Compiler Explorer actually keeps the entire file and does not search for functions, it just filters out certain lines. At least that is what the source code seems to be doing.

cargo-asm specifically appears to look for .cfi_endproc on Linux and Mac, and .seh_endproc on Windows.

Upvotes: 2

Related Questions