Skip to main content

How It Works

MemBrowse integrates into your CI pipeline to analyze every build. It parses your ELF file and linker script, extracts memory usage data, and uploads a report to the MemBrowse Portal. Your source code and binary never leave your infrastructure.

On pull requests, MemBrowse posts a comment showing exactly how much memory the change adds or removes, giving reviewers visibility before merging.

MemBrowse can also serve as a CI gate: if memory usage exceeds your configured budgets, the CLI exits with a non-zero code, failing the build and preventing the merge. This ensures memory regressions are caught before they reach your main branch.

Key Terminology

Targets

A target represents a specific build configuration. If you build for multiple boards (stm32f4, nrf52840), build types (debug, release), or feature variants (with-bluetooth, minimal), each is a separate target with its own independent history.

For library projects, a target can also be a usage example or test application that exercises the library, giving you a representative view of memory impact.

Memory Regions

Memory regions are the physical memory banks on your device, defined in your linker script. MemBrowse supports both GNU LD (.ld) and IAR ICF (.icf) linker script formats.

For GNU LD scripts, MemBrowse reads the MEMORY block to understand the origin and size of each region:

MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 64K
CCM (rwx) : ORIGIN = 0x10000000, LENGTH = 8K
}

From this, MemBrowse knows the total capacity of each region and calculates usage percentages. Common regions include:

  • FLASH: Non-volatile storage for code and constants
  • RAM: Volatile memory for variables, stack, and heap
  • Custom regions: Board-specific memory like CCM, ITCM, DTCM, or external RAM

Sections

Sections are logical groupings that map into memory regions. They are defined in the linker script's SECTIONS block:

SECTIONS
{
.text : { *(.text*) } > FLASH
.rodata : { *(.rodata*) } > FLASH
.data : { *(.data*) } > RAM AT > FLASH
.bss : { *(.bss*) } > RAM
}

Symbols

Symbols are individual functions and variables. MemBrowse extracts the name, size, section, and source file for each symbol, giving you a granular view of where memory is spent. This lets you sort by size, filter by section, and identify the biggest consumers to target for optimization.

What Gets Analyzed

MemBrowse needs two inputs from your build:

  1. ELF file: The compiled binary containing all symbol and section information
  2. Linker script (optional): Defines memory regions and their sizes — supports GNU LD (.ld) and IAR ICF (.icf) formats. If omitted, MemBrowse infers memory regions from ELF section flags.

For the most accurate results, compile with debug symbols (-g flag). Debug symbols help MemBrowse map symbols to source files and provide meaningful names. They increase ELF file size but don't affect the final binary deployed to your device.

If you want to strip debug symbols from the binary after uploading to MemBrowse, use:

arm-none-eabi-objcopy --strip-debug firmware.elf firmware-stripped.elf

Data Privacy

  • ELF files are analyzed locally in your CI environment
  • Source code never leaves your infrastructure
  • Only JSON reports are uploaded, containing symbol metadata (names, sizes, addresses)
  • Enterprise users can deploy MemBrowse on-premises for complete data control. Contact us to learn more.