MemBrowse

A tool for analyzing binary size and memory footprint of embedded firmware. MemBrowse extracts detailed memory information from ELF files and linker scripts, providing symbol-level analysis with source file mapping for multiple architectures. Use it standalone for local analysis or integrate with MemBrowse for historical analysis and CI integration.
Features
- Architecture Agnostic: Works with architectures that produce ELFs with DWARF debug format
- Source File Mapping: Symbols are mapped to their definition source files
- Memory Region Extraction: Memory region capacity and layout are extracted from GNU LD and ICF linker scripts
- Cloud Integration: Upload reports to MemBrowse for historical tracking, diffs, monitoring and CI gating
CI/CD Integration
GitHub Actions
MemBrowse provides GitHub Actions for CI integration.
PR/Push Analysis
Create a Github action for PR analysis that will call membrowse/membrowse-action:
name: Memory Analysis
on: [push, pull_request]
jobs:
analyze:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build firmware
run: make all # your build commands
- name: Analyze memory
uses: membrowse/membrowse-action@v1
with:
elf: build/firmware.elf # your elf
ld: "src/linker.ld" # your ld scripts
target_name: stm32f4 # the target name will be recognized by MemBrowse
api_key: ${{ secrets.MEMBROWSE_API_KEY }}
- name: Post PR comment
if: github.event_name == 'pull_request'
uses: membrowse/membrowse-action/comment-action@v1
with:
api_key: ${{ secrets.MEMBROWSE_API_KEY }}
commit: ${{ github.event.pull_request.head.sha }}
# Optional: use a custom Jinja2 template for the comment
# comment_template: .github/membrowse-comment.j2
The comment action posts a memory report to the PR showing changes between the PR branch and the base branch. The report includes memory region utilization changes (e.g. FLASH, RAM), section-level deltas (e.g. .text, .bss, .data), and symbol-level changes — added, removed, modified, and moved symbols. If budget alerts are configured on MemBrowse, any exceeded budgets are highlighted in the comment.
You can customize the comment format by providing a Jinja2 template via the comment_template input. Your template receives a targets list (each with regions, sections, symbols, and alerts) and a top-level has_alerts boolean. See the default template for reference.
Tracking overflow past the real region size (optional limits)
By default, the linker refuses to produce an ELF when a region overflows, so there's nothing to analyze. If you want to keep building (and keep tracking memory growth) past that point, link against an inflated linker script whose LENGTH values are larger than the real target, and pass the real script as limits:
- name: Analyze memory
uses: membrowse/membrowse-action@v1
with:
elf: build/firmware.elf
ld: "src/linker.inflated.ld" # used for linking + section attribution
limits: "src/linker.real.ld" # real per-region LENGTH → utilization & overflow
target_name: stm32f4
api_key: ${{ secrets.MEMBROWSE_API_KEY }}
limits is optional — omit it when the binary fits the real layout (then ld is already the real limit). When supplied, section-to-region attribution still uses ld (so sections placed past the real end stay attributed to their region), and utilization / free / overflow are reported against each region's LENGTH from limits.
Historical Onboarding
For getting historical build data from day one upload the last N commits by
Creating an Onboard Github action in your repo that will call membrowse/membrowse-action/onboard-action:
name: Onboard to MemBrowse
on: workflow_dispatch
jobs:
onboard:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
fetch-depth: 0