Skip to main content

Memory footprint analysis tools for embedded firmware

Project description

MemBrowse

PyPI version Python Versions License: GPL v3 Downloads

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.json configuration
  • 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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

membrowse-1.1.10.tar.gz (195.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

membrowse-1.1.10-py3-none-any.whl (118.4 kB view details)

Uploaded Python 3

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

Hashes for membrowse-1.1.10.tar.gz
Algorithm Hash digest
SHA256 b7b81a69b3d85c2d7258ed328dd75c2d1dcde3809dde40f85b0934786c3eac25
MD5 09edef91305a0708972ccc788e7a3469
BLAKE2b-256 f058200bfe948176a8f995683bb2e17270ff1acb9470799542d526440c47c873

See more details on using hashes here.

Provenance

The following attestation bundles were made for membrowse-1.1.10.tar.gz:

Publisher: publish-to-pypi.yml on membrowse/membrowse-action

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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

Hashes for membrowse-1.1.10-py3-none-any.whl
Algorithm Hash digest
SHA256 5419e6672e1173d2c6f02a2e87cf271268f112daf42de5a91dcf8ce04bbe9055
MD5 12579feb22920f6a9584ac166383f4ce
BLAKE2b-256 5d45b4219738c903f98eaf6c419950ab7abed9c2119de0b701c0227b78842349

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page