# Keystone Engine: A Multi-Architecture Assembler Framework for Tooling

> Keystone is an LLVM-derived assembler library with a C/C++ core and bindings for Python, Rust, Go and others. It suits people who need to turn assembly text into machine code at runtime, and its dual GPLv2/commercial licence is the first thing to check.

**keystone-engine/keystone** — Keystone assembler framework: Core (Arm, Arm64, Hexagon, Mips, PowerPC, Sparc, SystemZ & X86) + bindings

- Repository: https://github.com/keystone-engine/keystone
- Website: http://www.keystone-engine.org
- Stars: 2,637 · Forks: 541
- Language: C++
- License: GPL-2.0
- Published: 2026-09-28 · Updated: 2026-09-28 · Language: en
- Canonical page: https://hysenlabs.com/projects/keystone-engine-keystone

## The problem Keystone solves: assembling at runtime, not at build time

Most assemblers are command-line programs. You write a .s file, run the assembler, and get an object file. That model breaks down when the assembly text is produced while your program is running. A disassembler that lets a user edit an instruction and write it back needs an assembler callable from code. An exploit development tool that generates shellcode for several architectures needs the same thing. A fuzzer that mutates instruction encodings needs to turn candidate mnemonics into bytes without shelling out.

Keystone is that assembler as a library. The README describes it as a "lightweight multi-platform, multi-architecture assembler framework" and states that it is implemented in C/C++ with bindings for Java, Masm, C#, PowerShell, Perl, Python, NodeJS, Ruby, Go, Rust, Haskell, VB6 and OCaml. The intended audience is tool builders, not people assembling a single file by hand. If you only need to assemble one source file once, your system assembler already does that and Keystone adds a dependency for nothing.

The architecture list is the other half of the pitch. The README claims support for Arm, Arm64 (AArch64/Armv8), Ethereum Virtual Machine, Hexagon, Mips, PowerPC, RISC-V, Sparc, SystemZ and X86 including 16, 32 and 64 bit modes. One API covering that range is the reason projects embed it rather than wrapping several toolchains.

## How the Keystone engine is put together

The repository layout shows the shape of the project. There is an llvm/ directory at the top level, and the README says Keystone "is based on LLVM, but it goes much further". The assembler tables and instruction encoders come from LLVM's MC layer, which is why the architecture coverage is broad without the project writing an encoder per target. The public surface is in include/, the command-line front end is in kstool/, and language bindings live under bindings/.

The API is described in the README as "clean/simple/lightweight/intuitive architecture-neutral". In practice that means you open a handle for a chosen architecture and mode, hand it assembly text, and get bytes back. The architecture-neutral part matters: the same call sequence works whether the target is X86 or Arm64, with the architecture and mode selected when the handle is created. The README also states that the engine is thread-safe by design, which is a claim about concurrent use of separate handles rather than a promise that any single handle can be shared freely.

Two entry points exist. You can link the library, or you can use kstool, the command-line assembler that ships in the repository. kstool is the fastest way to see what the engine does before committing to a binding.

## Installing Keystone and assembling your first instruction

The README does not put build steps in the main file. It points at docs/COMPILE.md for how to compile and install Keystone, and at docs/README.md for further documentation. The top level also carries platform-specific build scripts (make-lib.sh, make-share.sh, nmake-dll.bat, nmake-lib.bat) and a CMakeLists.txt, so both CMake and the shell scripts are supported entry points. Because the LLVM sources are vendored in llvm/, expect a long first build; this is not a small C file you compile in a second.

Once the library is built, the samples/ directory is the shortest path to a working example. It contains sample.c plus a Makefile, nmake.bat and CMakeLists.txt. Those are the files the repository ships, and they are the ones to open first; the exact call signatures for each language binding are documented under bindings/.

For the command line, kstool is the assembler front end built from this repository. Build it the same way as the library, then run it against a line of assembly for the target you built. If the input is invalid, the tool reports an error rather than emitting partial bytes, so check the exit status when you script it. The architecture and mode are selected per invocation; assembling for a different target means a different invocation rather than a shared state change.

## Where Keystone is the wrong tool

The release history is the first limitation. The most recent tagged release is 0.9.2, dated 2020-06-21. The two entries before it are 0.9.2-rc1.post2 and 0.9.2-rc1.post1 from June 2020. Anyone who installs from a distribution package or a language package manager is getting a snapshot of the engine as it stood then. The repository itself is not archived and the last push was on 2026-07-18, so development has continued on master, but that work has not been cut into a release. If your project needs a specific recent instruction or a newer architecture, check whether it exists in 0.9.2 before assuming it is there.

There is a visible gap between the README's architecture list and the release. The README names Ethereum Virtual Machine and RISC-V alongside the older targets, while the description of the repository lists Core support as Arm, Arm64, Hexagon, Mips, PowerPC, Sparc, SystemZ and X86. Treat the README as the project's intent and the release tags as what a package manager will actually give you.

Keystone is also an assembler only. It does not disassemble. If your tool needs to go both ways, you need a second library for the reverse direction, and the two will not necessarily agree on syntax or operand ordering. And if your assembly text is a full program with sections, relocations and symbols, a library that encodes individual instructions is the wrong level of abstraction; use a real assembler and linker.

## Keystone compared with using LLVM's MC layer directly

The honest alternative is LLVM itself. Keystone's encoders come from LLVM's MC layer, so a project willing to depend on a full LLVM build can call into that layer directly, or use the MCJIT path, and get the same instruction encoders. The difference is scope and interface. LLVM exposes the MC layer as part of a compiler infrastructure: the API is larger, the build is larger, and the abstractions are shaped around code generation rather than around "give me bytes for this string". Keystone wraps that into a small architecture-neutral call and ships the LLVM sources inside its own tree so the user does not have to match versions.

That trade-off has a cost in both directions. Keystone gives you a smaller API and a self-contained build, but you inherit its release cadence, which as noted is far behind master. Going straight to LLVM gives you current encoders and the option to track upstream, at the price of a much heavier dependency and an API that was not designed for this use case. For a Python tool that needs to assemble a handful of instructions for three architectures, the wrapper is the better fit. For a compiler-adjacent project already linking LLVM, adding Keystone means carrying a second copy of the same code.

## Licence and what it means for distribution

Keystone is dual licensed, and the README is explicit about both halves. The open source option is version 2 of the GNU General Public License, and the README notes the important detail that it is GPLv2 "without the 'any later version' clause". That means you cannot relicense under GPLv3 by taking the upgrade option; the terms you get are the ones in COPYING. The repository also carries an EXCEPTIONS-CLIENT file, and the README states that the GPLv2 plus exceptions combination "allows almost all of open source projects to use Keystone without conflicts". If you are distributing an open source project that links Keystone, read COPYING and EXCEPTIONS-CLIENT together before deciding what your own licence can be.

The second option is commercial. The README says that for commercial usage in production environments you should contact the authors to buy a royalty-free licence, and points at LICENSE-COM.TXT for details. This is the path for a closed source product that cannot ship under GPLv2. The practical consequence for evaluation is that Keystone is not simply free to embed anywhere. If your product is proprietary and you do not want to buy a licence, Keystone is off the table regardless of how well the API fits. This is a description of what the repository states, not legal advice; the terms in the files govern.

## Maintenance cost and what to expect when upgrading

Two clocks run at once here. The repository is alive: it is not archived and the last push was on 2026-07-18. The release channel is not: the newest tag is 0.9.2 from 2020-06-21. A team that installs from a package manager gets the 2020 engine and will not see fixes or new instructions until someone cuts a release. A team that builds from master gets the current code but takes on the cost of tracking a moving branch that vendors LLVM, which means rebuilds are long and a bad commit can break the build with no tagged fallback that contains the same features.

Upgrading is therefore not a routine dependency bump. Because the LLVM sources live inside the repository rather than being an external dependency, you cannot simply raise a version number and let your package manager resolve it; you rebuild the whole tree. The practical approach is to pin a specific commit, build it in CI, and only move the pin deliberately. The ChangeLog and RELEASE_NOTES files at the top level are where the project records what changed between versions, and they are the first place to look before moving a pin.

## Conclusion

Keystone fits reverse-engineering tools, emulators, patchers and fuzzers that need to assemble instructions for several architectures at runtime, especially when the language doing the work is Python or Rust. It is the wrong choice if you need an up-to-date ISA surface, because the last tagged release is 0.9.2 from 2020-06-21 and the README's architecture list already runs ahead of it; build from master if you need the newer targets. Before adopting, verify three things: that your target architecture and instruction set are actually covered, that your distribution is acceptable under GPLv2 or that you can buy the commercial licence described in LICENSE-COM.TXT, and that you can build the bundled LLVM from source on your platform. The repository is not archived and the last push was on 2026-07-18, so master still moves even though releases do not.

## FAQ

### What is Keystone Engine used for?

It is an assembler framework: a library and a command-line tool that turn assembly text into machine code for several architectures. The README describes it as a lightweight multi-platform, multi-architecture assembler framework implemented in C/C++ with bindings for languages including Python, Rust and Go.

### Which architectures does Keystone Engine support?

The README lists Arm, Arm64 (AArch64/Armv8), Ethereum Virtual Machine, Hexagon, Mips, PowerPC, RISC-V, Sparc, SystemZ and X86 including 16, 32 and 64 bit. The repository description lists the core as Arm, Arm64, Hexagon, Mips, PowerPC, Sparc, SystemZ and X86, so check the specific target you need against what your installed version actually provides.

### How do I install Keystone Engine?

The README does not give build steps in the main file; it points to docs/COMPILE.md for how to compile and install Keystone. The repository also ships CMakeLists.txt and platform scripts such as make-lib.sh and nmake-lib.bat, and the LLVM sources are vendored in the llvm/ directory, so the first build is substantial.

### What licence does Keystone Engine use?

It is dual licensed. The open source option is version 2 of the GNU General Public License without the any later version clause, with an EXCEPTIONS-CLIENT file that the README says lets almost all open source projects use it without conflicts. For commercial use in production environments the README directs you to contact the authors to buy a royalty-free licence, described in LICENSE-COM.TXT.

### Does Keystone Engine disassemble instructions as well as assemble them?

No. The README and repository describe an assembler framework only, with no disassembly capability mentioned. A tool that needs to go from bytes back to mnemonics requires a separate library for that direction.

## Sources

- [keystone-engine/keystone on GitHub](https://github.com/keystone-engine/keystone)
- [License: GPL-2.0](https://github.com/keystone-engine/keystone/blob/master/LICENSE)
- [Project website](http://www.keystone-engine.org)
- [README](https://github.com/keystone-engine/keystone/blob/master/README.md)
- [Releases](https://github.com/keystone-engine/keystone/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/keystone-engine-keystone
