memprobe is in free beta. Sign up now during beta to get 40% off Pro for life. See pricing

memprobe

Online ELF analyzer for embedded firmware.

Drop an ELF file. Flash and RAM usage broken down by symbol, section, and source file. Bloat flagged with the exact fix.

No account needed to analyze · Binaries never stored
Pricing
Free during beta. Pro coming soon.
See what's included in each plan and lock in early access pricing.
View pricing
nm · what you have now
00084000 r _ZL17VL53L5CX_FIRMWARE 00008000 b farZonePx 00007260 b _ZL4grid 00002fbc t _svfprintf_r 00002fd0 t _vfprintf_r
memprobe · what you get
_ZL17VL53L5CX_FIRMWARE84 KB.flash.rodata · SparkFun_VL53L5CX/src
farZonePx32 KB.dram0.bss · include/base/grid.h:28
_ZL4grid29 KB.dram0.bss · src/screens/map3d_screen.cpp:32
_svfprintf_r12 KB.flash.text · libc/stdio/local.h:154

A real ESP32 firmware analysis.

Every tab below is live, straight from the binary.
memprobe.dev/app
Analysis
firmware.elf
Flash
893.7 KB
~194.7 KB OTA
RAM
115.6 KB
Sections
156
4,013 symbols
Warnings
5
Binary info
Architecture
Xtensa
Chip family
ESP32 (Xtensa LX6/LX7)
Bitness
32-bit
ELF type
Executable
Endianness
little-endian
OS/ABI
ELFOSABI_SYSV
Entry point
0x40377734
ELF flags
0x300
Compiler
GCC: (crosstool-NG esp-2021r2-patch5) 8.4.0
OTA estimate
~194.7 KB compressed (65% of 299.5 KB raw) · zlib
Load segments (PT_LOAD)
VAddrPAddrFile sizeMem sizeFlags
0x3c0000200x3c000020509.4 KB509.4 KBrw-
0x3fc880000x3fc8800070.0 KB169.8 KBrw-
0x403740000x4037400070.2 KB70.2 KBrwx
0x420000200x42000020299.5 KB299.5 KBr-x
0x500000000x500000000 B16 Brw-
Sections
Name Size %
.flash_rodata_dummy
Read-only constant data.
320.0 KB
20.2%
.flash.text
Executable code stored in flash (ESP32)
299.5 KB
18.9%
.xt.prop
Xtensa property table. Toolchain metadata.
266.4 KB
16.8%
.flash.rodata
Read-only data in flash (ESP32)
189.1 KB
11.9%
.dram0.bss
Uninitialized data in DRAM (ESP32)
99.8 KB
6.3%
Show all 156 sections
Memory treemap
firmware
.flash_rodata
320.0 KB
.flash.text
290.7 KB
.xt.prop
266.4 KB
.dram0.bss
100.3 KB
.str…
132.2 KB
.symtab
118.0 KB
.fla…
118.3 KB
.ira…
59.6 KB
.dra…
54.2 KB
Symbol table 4,013 symbols
Name Size Section Source
_ZL17VL53L5CX_FIRMWARE86,016.flash.rodata…/SparkFun_VL53L5CX_Arduino_Library/src
farZonePx32,768.dram0.bssinclude/base/grid.h:28
_ZL4grid29,280.dram0.bsssrc/screens/map3d_screen.cpp:32
_ZL6s_path18,000.dram0.bsssrc/screens/tracker_screen.cpp:15
_vfprintf_r12,250.flash.text…/libc/include/stdio.h:503
_svfprintf_r11,979.flash.text…/libc/stdio/local.h:154
_vfiprintf_r8,354.flash.text…/libc/include/stdio.h:499
1–100 of 4,013
Call graph
Warnings
!
C++ exceptions linked (__cxa_throw). Unwind tables add flash overhead.
i
RTTI enabled: 5 typeinfo record(s), 56 bytes.
i
assert() linked with file/line strings (__assert_func). Each call site embeds __FILE__, __func__, and the expression in flash.
i
Stack canaries enabled (__stack_chk_fail). Each protected frame costs one extra stack word plus entry/exit checks.
i
'_ZL17VL53L5CX_FIRMWARE' is 84.0 KB in .flash.rodata.
Binary Insights Pro
Savings
881 B
recoverable flash
INFO 881 B 9 symbol(s) in multiple translation units. Link with -flto or --icf=safe to deduplicate
INFO 4.1 KB alignment padding between symbols
WARN C++ exceptions linked. Build with -fno-exceptions to remove unwind tables
File contributors
Source file Flash RAM
…/SparkFun_VL53L5CX_Arduino_Library/src/vl53l5cx_buff…
85.7 KB
0
lib/TFT_eSPI/TFT_eSPI.cpp
10.2 KB
0
src/managers/tab_manager.cpp
9.6 KB
1.2 KB
Export analysis
What to include
Select all · Clear
Format
Share a read-only link
Generates a public URL that anyone can open. The link contains the same analysis you see here. No login required to view.
Dead code Pro
Reachability

A function is listed only when no caller is reachable from the entry point, interrupt vectors, or any stored function pointer. 312 address-taken function(s) were kept on that basis.

100.1 KB
reclaimable
800
unreferenced
1,694 / 2,494
reachable
312
address-taken (kept)
Unreferenced functions
FunctionSizeSectionSource
esp_eth_ioctl2.4 KB.flash.text…/esp_eth/src/esp_eth.c
mbedtls_ssl_setup1.8 KB.flash.text…/mbedtls/library/ssl_tls.c
vl53l5cx_dci_write_data1.3 KB.flash.text…/vl53l5cx_api.c
ledc_set_fade_with_time872 B.flash.text…/driver/ledc.c
spi_bus_remove_device560 B.flash.text…/driver/spi_master.c
How to read this
  • Functions reached only through a computed pointer that never appears as a stored address word (e.g. relative jump tables) cannot be seen statically and are NOT listed here.
  • Candidates may already be dropped by the linker when --gc-sections is enabled; this report is most useful when it is not.
  • Verify before removing: confirm each symbol is unused in your own sources.
Stack usage Pro
6,816 B
worst-case stack fully bounded
frame source: .su (GCC -fstack-usage)
1,902 frames over 2,494 functions

Worst-case stack is the deepest sum of frame sizes along any call chain. It is a lower bound: paths through recursion, indirect calls, or dynamic allocation are flagged and never silently dropped.

Deepest call chain
app_main display_task lvgl_render decode_png tjpgd_decomp
Per entry point
Entry pointWorst-case depthBoundedNote
app_main6,816 Bbounded-
wifi_task3,072 Bbounded-
ipc_task2,304 Bbounded-
tiT1,984 Blower boundmakes an indirect call (callees unknown)
esp_timer1,536 Bbounded-

Also in your terminal and CI.

The same analysis from the command line, with a budget gate for CI.

Built for CI

Gate builds against flash and RAM budgets, and diff two builds. check exits non-zero when a budget is blown, so it drops straight into any pipeline.

Your binary never leaves your machine. Only section and symbol metadata is sent, the same data readelf and nm print.

Full reference in the docs.
1. Install
$pip install memprobe
2. Connect your account
$memprobe config set --key mp_live_xxxxxxxx
3. Analyze or gate a build
$memprobe analyze build/firmware.elf
$memprobe check build/firmware.elf # fails CI if over budget

From ELF to answers in seconds.

1

Drop your ELF file

Drag in the output from GCC or Clang: an ELF or AXF file. No install needed. Files are processed on the server and not stored after the request completes.

2

See exactly what's in your binary

Every section sized and colored. Every symbol (demangled if C++) traced back to its source file and line via DWARF. Compiler bloat flagged with the specific flag to fix it, like -fno-exceptions or --icf=safe.

3

Track builds, catch regressions

Save builds to a project and set a flash or RAM budget. When a commit pushes you over, you'll see exactly which symbols grew or appeared. Catch it on your machine, not during code review.

Everything nm and size don't tell you.

Drop a binary. Get answers.

No install. No account required to analyze. Sign up to save builds and track them over time.

Analyze for free
Sign up during beta and get 40% off Pro when it launches.