Memory footprint analysis tools for embedded firmware
Project description
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
id: analyze
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:
json_files: ${{ steps.analyze.outputs.report_path }}
# 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.
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
- name: Historical analysis
uses: membrowse/membrowse-action/onboard-action@v1
with:
num_commits: 100
build_script: "make clean && make" # your build commands
elf: build/firmware.elf # your elf file
ld: "components.ld memory.ld" #your ld scripts
target_name: my-target # the target name will be recognized by MemBrowse
api_key: ${{ secrets.MEMBROWSE_API_KEY }}
Claude Code Integration
If you use Claude Code, you can automatically set up MemBrowse integration using the membrowse-integrate skill.
First, add the MemBrowse plugin to Claude Code:
/plugin marketplace add membrowse@membrowse-action
Then run the skill in your project:
/membrowse-integrate
This will:
- Analyze your project's build system and targets
- Verify builds and linker scripts work locally
- Create
membrowse-targets.jsonconfiguration - Set up GitHub Actions workflows for PR analysis and onboarding
- Add a MemBrowse badge to your README
Local Installation
From PyPI
pip install membrowse
For Development
# Clone and install in editable mode
git clone https://github.com/membrowse/membrowse-action.git
cd membrowse-action
pip install -e .
Quick Start
Analyze Your Firmware Locally
The simplest way to analyze your firmware (local mode - no upload):
# Generate a human-readable report (default)
membrowse report \
build/firmware.elf \
"src/linker.ld src/memory.ld"
# Output JSON format instead
membrowse report \
build/firmware.elf \
"src/linker.ld src/memory.ld" \
--json
# Show all symbols (not just top 20)
membrowse report \
build/firmware.elf \
"src/linker.ld src/memory.ld" \
--all-symbols
# With verbose output to see progress messages
membrowse -v INFO report \
build/firmware.elf \
"src/linker.ld src/memory.ld"
By default, this generates a human-readable report with memory regions, sections, and top symbols. Use --json to output structured JSON data instead. Use -v INFO or -v DEBUG before the subcommand to see progress messages (default is WARNING which only shows warnings and errors).
Example output:
ELF Metadata: build/firmware.elf | Arch: ELF32 | Machine: EM_ARM | Entry: 0x0802015d | Type: ET_EXEC
=======================================================================================================================================
Region Address Range Size Used Free Utilization
--------------------------------------------------------------------------------------------------------------------------------------------
FLASH 0x08000000-0x08100000 1,048,576 bytes 365,192 bytes 683,384 bytes [██████░░░░░░░░░░░░░░] 34.8%
└─ FLASH_START 0x08000000-0x08004000 16,384 bytes 14,708 bytes 1,676 bytes [█████████████████░░░] 89.8%
• .isr_vector 392 bytes
• .isr_extratext 14,316 bytes
└─ FLASH_FS 0x08004000-0x08020000 114,688 bytes 0 bytes 114,688 bytes [░░░░░░░░░░░░░░░░░░░░] 0.0%
└─ FLASH_TEXT 0x08020000-0x08100000 917,504 bytes 350,484 bytes 567,020 bytes [███████░░░░░░░░░░░░░] 38.2%
• .text 350,476 bytes
• .ARM 8 bytes
RAM 0x20000000-0x20020000 131,072 bytes 26,960 bytes 104,112 bytes [████░░░░░░░░░░░░░░░░] 20.6%
• .data 52 bytes
• .bss 8,476 bytes
• .heap 16,384 bytes
• .stack 2,048 bytes
Top 20 Largest Symbols
======================
Name Address Size Type Section Source
--------------------------------------------------------------------------------------------------------------------------------------------
usb_device 0x20000a30 5,444 bytes OBJECT .bss usb.c
mp_qstr_const_pool 0x08062b70 4,692 bytes OBJECT .text qstr.c
mp_execute_bytecode 0x080392f9 4,208 bytes FUNC .text vm.c
fresh_pybcdc_inf 0x0806ffaa 2,598 bytes OBJECT .text factoryreset.c
emit_inline_thumb_op 0x0802ac25 2,476 bytes FUNC .text emitinlinethumb.c
mp_qstr_const_hashes 0x08061b36 2,334 bytes OBJECT .text qstr.c
stm_module_globals_table 0x08073478 2,096 bytes OBJECT .text modstm.c
stm32_help_text 0x08072366 2,067 bytes OBJECT .text help.c
mp_lexer_to_next 0x080229ed 1,768 bytes FUNC .text lexer.c
f_mkfs 0x080020ed 1,564 bytes FUNC .isr_extratext ff.c
...
Upload Reports to MemBrowse Platform
# Upload mode - uploads report to MemBrowse platform (https://membrowse.com)
membrowse report \
build/firmware.elf \
"src/linker.ld" \
--upload \
--target-name esp32 \
--api-key your-membrowse-api-key
# GitHub Actions mode - auto-detects Git metadata from CI environment
membrowse report \
build/firmware.elf \
"src/linker.ld" \
--upload \
--github \
--target-name esp32 \
--api-key your-membrowse-api-key
When uploading, MemBrowse will fail the build (exit code 1) if budget alerts are detected. Use --dont-fail-on-alerts to continue despite alerts.
Analyze Historical Commits (Onboarding)
Analyzes memory footprints across multiple commits and uploads them to MemBrowse:
# Analyze and upload the last 50 commits
membrowse onboard \
50 \
"make clean && make all" \
build/firmware.elf \
"STM32F746ZGTx_FLASH.ld" \
stm32f4 \
your-membrowse-api-key
Platform Support
MemBrowse works with toolchains that produce ELF files and supports GNU LD and ICF linker scripts. If you found that you're not getting optimal results please contact us: support@membrowse.com We are actively working on improving MemBrowse.
License
See LICENSE file for details.
Support
- Issues: https://github.com/membrowse/membrowse-action/issues
- Documentation: This README and inline code documentation
- MemBrowse Support: support@membrowse.com
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file membrowse-1.1.10.tar.gz.
File metadata
- Download URL: membrowse-1.1.10.tar.gz
- Upload date:
- Size: 195.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b7b81a69b3d85c2d7258ed328dd75c2d1dcde3809dde40f85b0934786c3eac25
|
|
| MD5 |
09edef91305a0708972ccc788e7a3469
|
|
| BLAKE2b-256 |
f058200bfe948176a8f995683bb2e17270ff1acb9470799542d526440c47c873
|
Provenance
The following attestation bundles were made for membrowse-1.1.10.tar.gz:
Publisher:
publish-to-pypi.yml on membrowse/membrowse-action
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
membrowse-1.1.10.tar.gz -
Subject digest:
b7b81a69b3d85c2d7258ed328dd75c2d1dcde3809dde40f85b0934786c3eac25 - Sigstore transparency entry: 1206480474
- Sigstore integration time:
-
Permalink:
membrowse/membrowse-action@56374b27d7bb5ce27c8ed49723924f81d94788ae -
Branch / Tag:
refs/tags/v1.1.10 - Owner: https://github.com/membrowse
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@56374b27d7bb5ce27c8ed49723924f81d94788ae -
Trigger Event:
release
-
Statement type:
File details
Details for the file membrowse-1.1.10-py3-none-any.whl.
File metadata
- Download URL: membrowse-1.1.10-py3-none-any.whl
- Upload date:
- Size: 118.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5419e6672e1173d2c6f02a2e87cf271268f112daf42de5a91dcf8ce04bbe9055
|
|
| MD5 |
12579feb22920f6a9584ac166383f4ce
|
|
| BLAKE2b-256 |
5d45b4219738c903f98eaf6c419950ab7abed9c2119de0b701c0227b78842349
|
Provenance
The following attestation bundles were made for membrowse-1.1.10-py3-none-any.whl:
Publisher:
publish-to-pypi.yml on membrowse/membrowse-action
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
membrowse-1.1.10-py3-none-any.whl -
Subject digest:
5419e6672e1173d2c6f02a2e87cf271268f112daf42de5a91dcf8ce04bbe9055 - Sigstore transparency entry: 1206480483
- Sigstore integration time:
-
Permalink:
membrowse/membrowse-action@56374b27d7bb5ce27c8ed49723924f81d94788ae -
Branch / Tag:
refs/tags/v1.1.10 - Owner: https://github.com/membrowse
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-to-pypi.yml@56374b27d7bb5ce27c8ed49723924f81d94788ae -
Trigger Event:
release
-
Statement type: