https://github.com/flavouredtux/ember
x86-64 decompiler built from first principles. ELF + Mach-O, IR + SSA, pseudo-C, QuickJS scripting.
https://github.com/flavouredtux/ember
cpp cpp23 decompiler disassembler elf mach-o reverse-engineering x86-64
Last synced: 3 days ago
JSON representation
x86-64 decompiler built from first principles. ELF + Mach-O, IR + SSA, pseudo-C, QuickJS scripting.
- Host: GitHub
- URL: https://github.com/flavouredtux/ember
- Owner: FlavouredTux
- License: other
- Created: 2026-04-18T17:01:52.000Z (9 days ago)
- Default Branch: main
- Last Pushed: 2026-04-23T21:44:19.000Z (4 days ago)
- Last Synced: 2026-04-23T23:33:50.946Z (4 days ago)
- Topics: cpp, cpp23, decompiler, disassembler, elf, mach-o, reverse-engineering, x86-64
- Language: C++
- Size: 2.28 MB
- Stars: 4
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Ember
A from-scratch reverse-engineering toolkit: ELF + Mach-O loader, x86-64
disassembler, IR lifter, SSA, cleanup passes, control-flow structuring,
pseudo-C emitter, a QuickJS scripting surface, and an Electron UI.
No Capstone. No Zydis. No Ghidra decompiler. Stdlib only (QuickJS-NG is
vendored for scripting).


## Build
Requires a C++23 compiler (GCC 15+ or recent Clang) and CMake 3.28+.
```sh
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j
./build/cli/ember --help
```
### UI
The Electron UI lives in `ui/`. It shells out to the `ember` CLI binary.
```sh
cd ui
npm install
npm run dev
```
Set `EMBER_BIN` if the CLI isn't at `../build/cli/ember`.
## CLI
```
ember [options]
-d, --disasm linear disassembly of a function
-c, --cfg control-flow graph of a function
-i, --ir lifted IR of a function
--ssa IR in SSA form (implies -i)
-O, --opt run cleanup passes (implies --ssa)
--struct structured regions (implies -O)
-p, --pseudo pseudo-C output (implies --struct)
-X, --xrefs emit full call graph (all fn -> call targets)
--strings dump printable strings (addr|text|xrefs)
--arities dump inferred SysV arity per function
-s, --symbol NAME target a specific symbol (default: main)
--annotations P read user renames / signatures from a project file
--project PATH project file scripts may read/write via project.*
--script PATH run a JS file against the loaded binary
-- ARG... pass remaining args to the script as argv
--cache-dir DIR override ~/.cache/ember
--no-cache bypass the on-disk cache
```
`--xrefs`, `--strings`, and `--arities` are cached to `~/.cache/ember/`
(keyed on path + size + mtime). First run is slow; subsequent runs on the
same binary skip the analysis entirely.
## Pipeline
```
ELF → decoder → CFG → IR lift → SSA →
cleanup passes → structurer (if/while/switch) → pseudo-C
```
x86-64 only. ELF and Mach-O.
## Scripting
`--script PATH` runs a JavaScript file with the loaded binary exposed
through `binary`, `xrefs`, `strings`, and (with `--project`) `project`.
```sh
ember --script scripts/query.js -- [args...]
```
`scripts/query.js` is a generic dispatcher covering `info`, `imports`,
`sections`, `bytes`, `disasm`, `func`, `pseudo-c`, `xrefs-to`, `callers`,
`callees`, `strings`, `string-xrefs`, `find-func`, `find-bytes`, and more.
Mutations (`project.rename`, `setSignature`, `note`) stage into a pending
buffer; `project.commit()` writes them back to the project file. Every
mutator also accepts `{ dryRun: true }` so agents can preview changes
before committing.
## Layout
```
core/ C++23 library (everything except the CLI shim)
include/ember/ public headers
src/
binary/ ELF + Mach-O loaders
disasm/ x86-64 instruction decoder
analysis/ CFG builder, SysV arity inference, strings scanner
ir/ IR + x64 lifter + SSA builder + cleanup passes
structure/ region builder (if / while / switch)
decompile/ pseudo-C emitter
script/ QuickJS runtime + bindings
common/ annotations (project file), on-disk cache
cli/ command-line driver
scripts/ JS scripts that run against the CLI (query.js, etc.)
ui/ Electron + React + TypeScript frontend
tests/ golden-output CTest suite
third_party/ vendored deps (QuickJS-NG)
```
## Tests
```sh
cmake --build build -j
ctest --test-dir build
```
Fixtures are small C programs compiled at build time; output is diffed
against checked-in goldens in `tests/golden/`. To accept an intentional
output change:
```sh
UPDATE_GOLDEN=1 ctest --test-dir build -V
```
## Status
Under active development. Output is readable enough to beat hand-reading
x64, but edges are rough — particularly around indirect calls, sub-register
arithmetic corner cases, and switch cases whose default target happens to
lie outside the table's bounds check.
## License
MIT. See [LICENSE](LICENSE). QuickJS-NG (vendored under `third_party/quickjs/`)
is also MIT.