Skip to content

membrowse/membrowse-action

Use this GitHub action with your project
Add this Action to an existing workflow or create a new one
View on Marketplace

Repository files navigation

MemBrowse

PyPI version Python Versions License: GPL v3 Downloads

A tool for analyzing memory footprint in 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 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 is with toolchains that produce ELF files and uses GNU LD 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