Skip to content

Add elf-mcp: arm binutils + linker-map data as MCP tools (issue-62) - #63

Merged
emrainey merged 2 commits into
developfrom
issue-62
Aug 30, 2026
Merged

Add elf-mcp: arm binutils + linker-map data as MCP tools (issue-62)#63
emrainey merged 2 commits into
developfrom
issue-62

Conversation

@emrainey

Copy link
Copy Markdown
Owner

Closes #62

What

New tools/elf-mcp/ MCP server (JSON-RPC 2.0 over stdio, mirroring pylink-square-mcp) that turns the ARM GNU binutils and GNU ld link-maps into structured-JSON tools for firmware flash/RAM analysis:

  • list_elf_files — discover firmware ELF/map artifacts under build/
  • binary_size — exact flash/RAM totals with per-section classification
  • section_breakdown — verbose readelf -S listing (debug sections too)
  • memory_map — fill % of each linker MEMORY region
  • largest_symbols — top-N symbols by size (bloat hunting)
  • per_object_map — per-object flash/RAM from the .map (function-sections + classic formats, discarded-section stripping)
  • verify_no_heap — scan for malloc / operator new / _cxa* / unwind
  • disassemble — function or address range disassembly
  • addr2line — PC -> function + source (pairs with pylink-square-mcp backtraces)

Structure

tools/elf-mcp/:

  • mcp_server.py — stdio server; wired into opencode.json
  • tools.py — 9 tool handlers + CLI + TOOLS registry
  • parsers.py — pure-text parsers (no subprocesses)
  • toolchain.py — arm-none-eabi binutils resolver
  • tests/ — 31 pytest cases, host-runnable without an ARM toolchain

Validation

  • binary_size on the M7 demo ELF matches arm-none-eabi-size exactly (flash 0xe0f4 / ram 0x37b20).
  • Per-object map flash total within ~2% of image total; RAM excludes linker-reserved stacks/DMA buffers by design.
  • verify_no_heap passes clean on the demo image.
  • 31/31 pytest; opencode config unchanged in semantics.

Checks

AI work (opencode, big-pickle): elf-mcp server/parsers/tests, opencode.json registration, all preset runs + validation.
Human work: .gitignore transient-file rules, CMakePresets.json DISTCC_DIR removal, external/CMakeLists.txt pip package list.

  • on-host-native-llvm workflow (21/21 tests)
  • on-host-native-clang workflow (21/21 tests)
  • on-target-cortex-m4-gcc-arm-none-eabi workflow
  • on-target-cortex-m7-gcc-arm-none-eabi workflow

AI work (opencode, model big-pickle):
- tools/elf-mcp/: JSON-RPC stdio MCP server exposing 9 analysis tools
  (list_elf_files, binary_size, section_breakdown, memory_map,
  largest_symbols, per_object_map, verify_no_heap, disassemble,
  addr2line) over arm-none-eabi binutils and GNU ld .map parsing.
- toolchain resolver, pure-text parsers, tool handlers + CLI entry.
- 31 pytest host tests (fake runner; no ARM toolchain required).
- Registered server in opencode.json; validated against the real M7
  demo ELF (flash 0xe0f4 / ram 0x37b20 matches arm-none-eabi-size).
- Ran on-host llvm/clang workflows (21/21 tests each) and the
  cortex-m4/m7 cross workflows; all green.

Human work:
- .gitignore: ignore transient TODO/PLAN/HANDOFF working files.
- CMakePresets.json: drop local DISTCC_DIR env var.
- external/CMakeLists.txt: pip install list (mcp-cmake, etc.).
AI work (opencode, big-pickle): removed mcp-cmake, which has no PyPI
distribution and broke the CI configure step (pip 'No matching
distribution found').
Human work: none for this commit.
@emrainey
emrainey merged commit 31b1f9f into develop Aug 30, 2026
2 of 4 checks passed
@emrainey
emrainey deleted the issue-62 branch August 30, 2026 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant