Skip to content

feat: add ARM disassembler operation#2156

Merged
GCHQDeveloper581 merged 3 commits intogchq:masterfrom
thomasxm:add-disassembler-arm
Mar 8, 2026
Merged

feat: add ARM disassembler operation#2156
GCHQDeveloper581 merged 3 commits intogchq:masterfrom
thomasxm:add-disassembler-arm

Conversation

@thomasxm
Copy link
Copy Markdown
Contributor

Summary

  • Adds new "Disassemble ARM" operation for ARM architecture disassembly
  • Uses Capstone disassembly framework with vendored capstone.min.js (includes upstream bug fix)
  • Supports ARM (32-bit), Thumb, and ARM64 (AArch64) architectures

Details

Supported Architectures

Architecture Modes
ARM (32-bit) ARM, Thumb, Thumb + Cortex-M, ARMv8
ARM64 (AArch64) Default

Features

  • Little Endian and Big Endian support
  • Configurable starting address for position-independent analysis
  • Toggle instruction hex bytes display
  • Toggle instruction position display

Why Capstone?

Capstone is the industry standard disassembly framework used by:

  • Radare2, Binary Ninja, IDA Pro plugins
  • Frida, Unicorn Engine, QEMU
  • Angr, Pwntools, ROPgadget

This ensures accurate disassembly for security research and binary analysis.

Test plan

11 automated tests covering ARM32, ARM64, and Thumb modes

Manual test vectors

ARM32:
Input: 0100a0e3 001081e0 001041e0
Output:
mov r0, #1
add r1, r1, r0
sub r1, r1, r0

ARM64:
Input: fd7bbfa9 fd030091 c0035fd6
Output:
stp x29, x30, [sp, #-0x10]!
mov x29, sp
ret

Thumb:
Input: 80b5 0844 80bd
Output:
push {r7, lr}
add r0, r1
pop {r7, pc}

Files changed

File Change
package.json Add @alexaltea/capstone-js dependency
src/core/operations/DisassembleARM.mjs New operation
src/core/vendor/capstone.min.js Vendored Capstone with bug fix
src/core/config/Categories.json Add to "Other" category
tests/operations/tests/DisassembleARM.mjs Test suite
tests/operations/index.mjs Register tests
Screenshot 2026-01-10 at 12 23 35

Copy link
Copy Markdown
Contributor

@GCHQDeveloper581 GCHQDeveloper581 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment this is pulling in capstone.min.js in two different ways (through the "@alexaltea/capstone-js" package, and through the vendor import) but only using the vendor import version.

I've checked and the package version can be used by changing the import in src/core/operations/DisassembleARM.mjs to

import cs from "@alexaltea/capstone-js/dist/capstone.min.js";

which still passes all your tests, and seems to work in browser.

This would be the slightly preferred method if there's not otherwise a problem with the npm package as it saves cluttering up the code base with additional vendor imports.

If the vendor import version is needed (and in which case there should be a test that distinguishes between the package and vendor import versions to avoid someone "cleaning up" at a later date) then the vendor import will need something at the top to establish provenance (where you've pulled it in from, and in particular what the "upstream bug fix" is), and to establish the MIT license that covers the code.

Either way the one you aren't using wants to be removed.

Otherwise looks pretty good (though I note there's currently a merge conflict).

thomasxm added 2 commits March 8, 2026 08:07
Add new Disassemble ARM operation using Capstone.js disassembly framework.

Features:
- ARM32 (ARM mode, Thumb mode, Thumb + Cortex-M, ARMv8)
- ARM64 (AArch64)
- Little/Big Endian support
- Configurable start address
- Optional hex and position display

Includes vendored capstone.min.js with fix for cs_disasm parameter bug.
Replace the vendored capstone.min.js with the import from the
@alexaltea/capstone-js npm package, as suggested in code review.
This avoids duplicating the library in the repository while the
npm dependency was already declared in package.json.
@thomasxm thomasxm force-pushed the add-disassembler-arm branch from 0eff656 to 6b88ed4 Compare March 8, 2026 12:58
@thomasxm
Copy link
Copy Markdown
Contributor Author

thomasxm commented Mar 8, 2026

Thanks for the review. I've switched to using the npm package import (@alexaltea/capstone-js/dist/capstone.min.js) and removed the vendored copy.

The upstream bug fix is a single line: the ccall to cs_disasm passes 7 arguments (Emscripten splits the uint64_t offset into two 32-bit values), but the npm version only declares 6 types in the array. The vendor copy fixes this to 7, which is technically correct. In test though, it makes no difference with this Emscripten build. ccall only runs converters for 'string' and 'array' types. Everything else, including 'number', 'pointer', and even the undefined you get from reading past the end of the types array, just gets passed through as-is. I couldn't produce any input that behaves differently between the two versions, so there's no practical distinguishing test to write. On that basis the npm package seemed the sensible route.

Also rebased onto current master so the merge conflict is resolved.

Copy link
Copy Markdown
Contributor

@GCHQDeveloper581 GCHQDeveloper581 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thanks for your contribution.

@GCHQDeveloper581 GCHQDeveloper581 merged commit a19261d into gchq:master Mar 8, 2026
2 checks passed
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