r2xsql
SQL interface for radare2, powered
by libxsql.
SELECT name, size FROM funcs WHERE name LIKE 'main%';
SELECT text FROM strings WHERE text LIKE '%password%';
UPDATE comments SET text = 'reviewed' WHERE addr = 0x1234;
r2xsql exposes radare2's analysis state as live SQL virtual tables: every
query re-issues the JSON form of the relevant r2 command (aflj, izj,
axtj, …) against an in-process core (r_core_cmd_str) or a spawned
radare2 -q0 pipe — no flat dump, no stale snapshot.
It's not read-only — and your work saves
Load the plugin in radare2 and mutate analysis through ordinary SQL writes.
Use radare2's -w option when writing binary bytes:
UPDATE funcs SET name = 'parse_header' WHERE addr = 0x401000; -- rename
UPDATE funcs SET prototype = 'int parse_header(char *buf)' WHERE name = 'parse_header';
INSERT INTO comments(addr, text) VALUES (0x401044, 'bounds check missing');
UPDATE locals SET name = 'len', type = 'int' WHERE func_addr = 0x401000 AND name = 'var_8h';
INSERT INTO types(name, kind) VALUES ('Header', 'struct');
INSERT INTO bookmarks(addr, name) VALUES (0x401000, 'entry-of-interest');
Writable surfaces: funcs (rename, prototype), comments, flags, locals (rename + retype), bookmarks, types (create struct/union/ enum), patches (byte edits), io_maps, bytes.
Persist it. Save analysis with Ps NAME in radare2 or
SELECT r2xsql_project_save('NAME') through SQL. Reopen it with P NAME or
SELECT r2xsql_project_open('NAME'). The plugin uses radare2's native project
format; it does not automatically save on exit.
Requirements
You need radare2. r2xsql does not bundle it and does not install it.
# any one of these
r2pm -ci radare2 # radare2's own package manager
git clone https://github.com/radareorg/radare2 && radare2/sys/install.sh
sudo apt install radare2 # distro package (may lag; see below)
brew install radare2 # macOS
Build core_r2xsql against the same radare2 installation that will load it:
the in-process plugin depends on radare2's ABI.
Using the plugin
Load the built module and analyze a target:
r2 -i /absolute/path/core_r2xsql.so -A ./target
Use the actual .so, .dylib, or .dll path; omit -i once the plugin is
installed in radare2's plugin directory. At the radare2 prompt:
sql SELECT name, size FROM funcs ORDER BY size DESC LIMIT 10
pdf @ entry0
q
For a one-shot query:
r2 -q -A -i /absolute/path/core_r2xsql.so \
-c '"sql SELECT name, size FROM funcs WHERE size > 100 LIMIT 5"' ./target
Each sql command executes one statement. Quote the whole r2 command when SQL
contains r2 operators such as > or |. Use repeated -c options, a radare2
command script, or a persistent session for multiple statements.
Build
Linux / macOS:
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DR2XSQL_BUILD_FULL=ON -DRadare2_ROOT=/path/to/radare2/prefix
cmake --build build
Windows (MSVC):
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 `
-DR2XSQL_BUILD_FULL=ON -DRadare2_ROOT=C:\path\to\radare2\prefix
cmake --build build --config Release
Radare2_ROOT is a radare2 install prefix containing include/libr/
and lib/. R2XSQL_BUILD_FULL=ON enables the libr backend and, when
R2XSQL_BUILD_PLUGIN=ON (the default), core_r2xsql in build/bin/
(build/bin/Release/ for the MSVC Release configuration).
Without R2XSQL_BUILD_FULL, CMake builds the backend-neutral static library
and examples, with no radare2 build dependency. The r2pipe backend remains
available to C++ consumers. R2XSQL_BUILD_EXAMPLES=OFF disables examples.
The project also supports being added as a CMake subdirectory.
Building the in-r2 plugin the radare2 way (Makefile / meson)
CMake above builds the library, examples, and plugin, including on Windows. If you
only want the in-r2 plugin — the core_r2xsql module that adds the sql
command inside radare2 — there is also a radare2-native build that needs no
CMake, matching how radare2 plugins are usually built (plugin paths from
r2 -H, radare2 from pkg-config r_core):
make # -> build-make/core_r2xsql.$(r2 -H R2_LIBEXT)
make user-install # install into the per-user plugin dir (no root)
make install # install system-wide (R2_LIBR_PLUGINS)
make test # load it in r2 and run one SQL query
# only `radare2` (not `r2`) on PATH? -> make R2=radare2
or with meson (what radare2 itself uses):
meson setup build-meson
meson compile -C build-meson
meson install -C build-meson # into R2_LIBR_PLUGINS
meson setup build-meson -Dr2_user_plugins=true # ... or the per-user dir
Both build the same plugin: the sql command. Both
consume libxsql: the Makefile uses a
sibling ../libxsql checkout (else clones it), and meson pulls it as a
subproject. A current libxsql is required (same as CMake's FetchContent).
JSON results
Use sqlj for programmatic queries and scripts:
"sqlj SELECT NULL AS missing, '' AS empty; SELECT count(*) AS n FROM funcs"
It returns libxsql's JSON envelope with per-statement columns, rows, errors,
and timings. SQL NULL is JSON null, distinct from the empty string. Quoting
the entire r2 command also preserves statement separators and SQL operators.
The same command works through r2pipe and radare2's HTTP /cmd/ endpoint.
HTTP access through radare2
Load the plugin in a persistent radare2 session and start r2's web server:
r2 -N -q -i /absolute/path/core_r2xsql.so \
-e http.bind=127.0.0.1 -e http.port=9090 -c aa -c '=h' ./target
Use the plugin's actual .so, .dylib, or .dll path. If it is installed,
omit -i. Send a quoted SQL command through r2's POST /cmd/ endpoint:
curl --data-binary '"sql SELECT name, size FROM funcs WHERE size > 100 LIMIT 5"' \
http://127.0.0.1:9090/cmd/
GET /cmd/<encoded-command> also works for short queries:
from urllib.parse import quote
from urllib.request import urlopen
sql = "SELECT name, size FROM funcs WHERE size > 100 ORDER BY size DESC LIMIT 5"
command = '"sql ' + sql.replace('"', '\\"') + '"'
with urlopen("http://127.0.0.1:9090/cmd/" + quote(command, safe="")) as response:
print(response.read().decode(), end="")
Quote the whole r2 command, escape any SQL double quotes, then URL-encode
it for GET; POST sends the quoted command as the raw body. URL encoding alone
does not protect SQL operators such as > and | from r2's command parser.
Prefer POST for longer SQL to avoid r2's request-line length limit.
Each request executes one SQL statement; the session
persists between requests, including analysis and comment changes.
Responses are the plugin's text tables, including the row count. SQL errors
appear as ERROR: ... in the body, even with HTTP status 200. The old
sql.http* and /query interface is removed;
configure the native server with r2's http.* settings instead.
Tests
After building the plugin, with radare2 and a C compiler on PATH:
python3 -m pip install pytest
python3 -m pytest -q tests
The tests load the plugin directly into radare2 and cover the SQL surface and
native HTTP integration (GET and POST). They find core_r2xsql in build/,
build-make/, build-meson/, or out/. Set R2XSQL_PLUGIN for other layouts
and R2_BIN to choose the matching radare2 executable. A missing plugin fails
the test run instead of silently skipping coverage.
Backends (internal detail)
The library retains these backends for embedding and testing:
| Backend | Used by | Notes |
|---|---|---|
R2PipeBackend |
C++ consumers (open_r2pipe) |
Spawns and manages radare2 -q0 over stdio. |
LibrBackend |
core_r2xsql and C++ consumers (open_libr) |
Uses radare2 in-process; the plugin wraps its host core. |
MockBackend |
embedding/tests | Canned {command → response} map, records issued commands — no live radare2. |
MockBackend |
In-memory mock: canned command→response map, records issued commands — for embedding/offline use without a live radare2. |
Skills (Claude Code / Codex)
Agent skills teach Claude Code and Codex to drive r2xsql: query and annotate
radare2 analysis through SQL, pick the right backend. They ship in the radare2 community skills catalog,
radare2-skills, as the
r2xsql/ category alongside dev/ and radius2/. Install a category
with its make install (or python install.py install for r2xsql/, which copies
rather than symlinks so it needs no elevated rights on Windows).
Start with the connect skill; its references/schema-catalog.md is the
canonical reference for the SQL surface.
License and Terms of Use
In short: you may read, build, evaluate, benchmark, package, and use unmodified r2xsql, including commercially, if you preserve notices and follow the license terms. You may fork or patch it to prepare bug fixes, optimizations, features, tests, or documentation improvements for contribution back within the license's contribution-purpose rules.
You may not maintain a divergent private fork, port, rebrand, clone, API-compatible replacement, competing implementation, or use r2xsql as AI input to recreate or improve a derivative implementation without prior written permission from Elias Bachaalany. Independent implementations that are not copied from, materially derived from, or substantially informed by r2xsql in the license's defined sense are not prohibited.
Permission requests: open a GitHub issue at radareorg/r2xsql/issues.
If r2xsql materially informs a distributed project, preserve the human origin: credit r2xsql and Elias Bachaalany visibly in your README/docs and in About/credits UI when applicable. The license includes an examples/FAQ section for common allowed and permission-required uses. Third-party dependencies (libxsql, radare2 (libr / r2pipe), and their transitive dependencies) remain under their own licenses.
See the full Human-Origin Source License v1.0.