Skip to content

msl: Memory Slice (.msl) plugins (io/bin/debug/core)#394

Merged
trufae merged 4 commits into
radareorg:masterfrom
reverseame:feat/msl-plugins
Jun 27, 2026
Merged

msl: Memory Slice (.msl) plugins (io/bin/debug/core)#394
trufae merged 4 commits into
radareorg:masterfrom
reverseame:feat/msl-plugins

Conversation

@ricardojrdez

Copy link
Copy Markdown
Contributor

Loadable radare2 plugins for the Memory Slice (.msl) process-dump format, packaged as a self-contained msl/ directory (build with the local Makefile via pkg-config r_core, or install through r2pm).

Plugin Role
io_msl open a slice as a process address space (msl://); verifies the SHA-256 block chain and End-of-Capture FileHash on open, warning on a truncated or tampered slice
bin_msl parse a slice as a CORE object (arch/bits/os, entry, maps)
debug_msl emulated ESIL debug backend, incl. reverse execution (dsb/aesb)
core_msl producer: dgm/dgma write a slice from a live debug session

test/genmsl.py emits a valid synthetic slice for exercising the read path without a live target. See msl/README.md for usage.

🤖 Generated with Claude Code

Loadable radare2 plugins for the Memory Slice process-dump format:

- io_msl    open a slice as a process address space (msl://); verifies
            the SHA-256 block chain and End-of-Capture FileHash on open,
            warning on a truncated or tampered slice
- bin_msl   parse a slice as a CORE object (arch/bits/os, entry, maps)
- debug_msl emulated ESIL debug backend, incl. reverse exec (dsb/aesb)
- core_msl  producer: "dgm"/"dgma" write a slice from a live debug session

Build/install with the local Makefile (pkg-config r_core) or via r2pm.
test/genmsl.py emits a valid synthetic slice for exercising the read path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
A slice can capture several threads (one Thread Context block each); the debug
backend only seeded the Current thread. Expose every captured thread:

- .threads callback: `dpt` / `dptj` lists each captured thread with its PC.
- .select callback: `dpt=<tid>` re-seeds the register file from that thread
  and seeks to its captured PC, so any thread can be emulated.

msl_seed_regs now takes a target tid (>=0 exact, <0 Current with first-thread
fallback) and reports the chosen tid, which msl_ensure stores in dbg->tid.

Also fixes a double-unref of the mmap buffer (msl_seed_regs used to unref a
buffer owned by its caller), and accounts for r_debug_select swapping the
register arena after .select returns (seed both arenas so the new thread's
registers survive the swap). test/genmsl.py gains --mt to emit a second,
non-Current thread for exercising listing and selection.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ricardojrdez

Copy link
Copy Markdown
Contributor Author

Pushed a follow-up commit (msl: select and list captured threads in the debug backend) on this branch, since it builds directly on the plugins here.

A slice can capture several threads (one Thread Context block each). The debug backend previously seeded only the Current thread; this exposes all of them via the standard r2 thread commands:

  • dpt / dptj — list every captured thread with its PC
  • dpt=<tid> — re-seed the register file from that thread and seek to its PC

It also fixes a double-unref of the mmap buffer in the register seeder, and test/genmsl.py gains --mt to emit a second non-Current thread for testing. Happy to split this into its own PR once the base plugins land if you'd prefer.

🤖 Generated with Claude Code

The bin plugin presented a slice as maps only. Parse ModuleEntry (0x0002)
blocks and expose them as libraries (`il`) and symbols (`is`): one symbol per
module base plus, for PE images whose headers are captured, one FUNC symbol per
exported function at its address. A VA->file-offset translator over the
captured-run maps reads the module image (DOS/PE headers, export directory).
radare2 then names call targets -- `sym.kernel32.dll_CreateFileW` -- instead of
bare addresses.

test/genmsl.py gains --pe (a minimal in-memory PE export table) and a
memory_region() helper. ELF .dynsym resolution is left to the Python tools.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ricardojrdez

Copy link
Copy Markdown
Contributor Author

Added another follow-up commit (msl: resolve module symbols and PE exports in bin.msl): the bin plugin now parses ModuleEntry blocks and exposes modules as libraries (il) and symbols (is), including PE export tables read from captured memory, so radare2 names call targets (sym.<dll>_<Export>) instead of bare addresses. test/genmsl.py gains --pe. ELF .dynsym resolution stays in the Python tools for now.

The debug.msl row documented reverse execution but not the `dpt` / `dpt=<tid>`
thread listing and selection; mention it for consistency with the body.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@trufae trufae merged commit f28a2ec into radareorg:master Jun 27, 2026
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.

2 participants