Is Binary Compiled with Frame Pointer Support?

· klm's blog

Explanation and script to check whether a Linux binary is compiled with -fomit-frame-pointer or not.

Original post is here: eklausmeier.goip.de

How can you detect whether a Linux binary was compiled with

1gcc -fomit-frame-pointer

Unfortunately the ELF itself does not contain a flag, which tells you that. But looking at the assembler code can give you the answer.

First disassemble the code with

1objdump -d

Check the disassembly for below pairs directly after any C function:

push   %rbp
mov    %rsp,%rbp

These are the instructions to set up the frame pointer on 64 bit Linux x86 systems.

Example:

0000000000001380 <zif_md4c_toHtml>:
    1380:       55                      push   %rbp
    1381:       48 89 e5                mov    %rsp,%rbp

A good heuristic is then

1objdump -d $binary | grep -c "mov.*%rsp,.*%rbp"

Double check with

1objdump -d $binary | grep -C1 "mov.*%rsp,.*%rbp"

This heuristic is not fool proof, as individual C routines can be augmented with

1__attribute__((optimize("omit-frame-pointer"))

In the intense debate about making -fno-omit-frame-pointer the default in Fedora, see this comment from L. A. F. Pereira in Python 3.11 performance with frame pointers.

See How can I tell whether a binary is compiled with frame pointers or not on Linux?, which discusses the case for 32 bit x86 Linux systems.

Code with framepointers will always contain the both of the two instructions push %ebp and mov %esp, %ebp. ... For those working with x86_64, the registers to look for are the 64-bit equivalents: %rbp and %rsp - the concept is the same though!

The post The Return of the Frame Pointers by Brendan Gregg triggered this task.

As of today, 18-Mar-2024, Arch Linux still does not ship binaries with frame pointer support. For example:

1$ objdump -d /bin/zsh | grep -c "mov.*%rsp,.*%rbp"
210

The PHP binary fails the heuristic:

1$ objdump -d /bin/php | grep -c "mov.*%rsp,.*%rbp"
2173

But looking at the actuall disassembly shows something like this:

000000000021aff2 <php_info_print_box_end@@Base>:
  21aff2:       f3 0f 1e fa             endbr64
  21aff6:       48 8d 05 43 9b 1e 01    lea    0x11e9b43(%rip),%rax        # 1404b40 <sapi_module@@Base>

I.e., no frame pointer handling.