Document agent workflows and fix Windows runtime DLL placement

This commit is contained in:
Elias Bachaalany authored and GitHub committed 2026-10-14 07:52:38 +02:00
1 parent 16da52e29f
commit 248bcdc83f
5 files changed
+495 -279

No files matched your search

+57 -274
View File
@@ -3,310 +3,93 @@
[![ci status](https://github.com/radareorg/r2xsql/actions/workflows/build.yml/badge.svg?branch=main)](https://github.com/radareorg/r2xsql/actions/workflows/build.yml?query=branch%3Amain)
SQL interface for [radare2](https://github.com/radareorg/radare2), powered
by [`libxsql`](https://github.com/0xeb/libxsql).
```sql
SELECT name, size FROM funcs WHERE name LIKE 'main%';
SELECT content FROM strings WHERE content LIKE '%password%';
UPDATE comments SET text = 'reviewed' WHERE addr = 0x1234;
```
`r2xsql` exposes radare2's analysis state as live SQL virtual tables: every
query reads native analysis data or the JSON form of the relevant r2 command
(`aflj`, `izj`, `axtj`, …) from an in-process core or a spawned `radare2 -q0`
pipe. Most live tables cache rows only for the duration of a query.
## 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:
```sql
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 and reopen it with
`P NAME`. The plugin uses radare2's native project format; it does not
automatically save on exit.
Project save/open and full type declarations use native radare2 commands:
`Ps NAME`, `P NAME`, and `"td struct Header { int magic; };"`. The former SQL
functions `r2xsql_project_save`, `r2xsql_project_open`, and
`r2xsql_type_define` are removed. SQL can still list/delete projects and
create empty struct/union/enum types through the corresponding tables.
## Requirements
**You need radare2.** r2xsql does not bundle it and does not install it.
```bash
# 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 behind releases)
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.
by [libxsql](https://github.com/0xeb/libxsql). The `core_r2xsql` plugin exposes
the host's live analysis as SQL tables, including writable annotations.
## Using the plugin
The recommended way to install the plugin is with r2pm:
Install radare2 first, then build and install the matching plugin with r2pm:
```sh
r2pm -U
r2pm -ci r2xsql
```
The installed plugin loads automatically when radare2 starts:
```sh
r2 -A ./target
```
At the radare2 prompt:
Installed plugins load automatically. Check `Lcj` and `sql?` at the r2 prompt.
For an uninstalled build, use `r2 -i ./core_r2xsql.so -A ./target`; inside an
existing session use `L ./core_r2xsql.so`. Substitute `.dylib` or `.dll` as
appropriate. The plugin must match the host's radare2 ABI, including iaito's
engine. See [installation details](docs/usage.md#installation).
```text
sql SELECT name, size FROM funcs ORDER BY size DESC LIMIT 10
pdf @ entry0
q
"sql UPDATE funcs SET name='parse_header' WHERE addr=0x401000"
"sqlj SELECT name FROM funcs WHERE size > 100"
```
For a one-shot query:
Use `sql` for a native r2 table, `sql,:csv` for CSV, and `sqlj` for the JSON
envelope and multiple statements. Wrap the whole command in double quotes
to protect SQL operators from r2's parser. See [SQL access](docs/sql.md).
```sh
r2 -q -A \
-c '"sql SELECT name, size FROM funcs WHERE size > 100 LIMIT 5"' ./target
```
## Analyze by asking your agent
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.
Install the [r2xsql skills](https://github.com/radareorg/radare2-skills/tree/main/r2xsql#install)
alongside the plugin, then ask naturally:
`sql` uses radare2's table renderer and honours `cfg.table.format` and
`scr.utf8`. Add a table query immediately after the command, before the SQL:
> Open `target.exe` headlessly and show me the ten largest functions.
>
> Rename that function based on its disassembly and pseudocode.
>
> Save the project beside the executable and keep it open.
The agent uses native radare2 and curl, writes SQL for you, and reuses the
session on follow-ups. Saving preserves a native r2 project; SQL results are
computed from its analysis. See the [workflow guide](docs/usage.md).
## Tandem mode
Share an analysis session from r2's prompt, its visual/panels text interface,
or [iaito](https://github.com/radareorg/iaito). Open and analyze the binary,
check that r2xsql loaded, then enter these commands in the r2 prompt or
iaito's **View > Console**:
```text
sql,:csv SELECT name, size FROM funcs
sql,size/gt/100,:quiet SELECT name, size FROM funcs
sql,?
e http.bind=127.0.0.1
e http.sandbox=false
e http.port=9090
=h&
```
Use `sql,:tsv` for tab-separated output. Native tables have no SQL NULL type;
in particular, `sql,:json` omits NULL and empty-string cells.
Choose a free port and wait for the server banner. Tell your agent:
**Use r2xsql at http://127.0.0.1:9090 on the binary already open here.**
The background server leaves the UI available. Take turns when changing
analysis; use distinct ports for several sessions. See [tandem mode](docs/usage.md#tandem-mode).
For a local build, `make user-install` also installs the plugin for automatic
loading. To load a build without installing it, use either `-i` or `L`:
## Fully headless
With an installed plugin, start a fresh binary in a background native process:
```sh
r2 -i /absolute/path/core_r2xsql.so -A ./target
r2 -A -c 'L /absolute/path/core_r2xsql.so' ./target
```
Use the actual `.so`, `.dylib`, or `.dll` path. Inside an existing radare2
session, use `L /absolute/path/core_r2xsql.so`.
## Build
Linux / macOS:
```sh
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DRadare2_ROOT=/path/to/radare2/prefix
cmake --build build
```
Windows (MSVC):
```powershell
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 `
-DRadare2_ROOT=C:\path\to\radare2\prefix
cmake --build build --config Release
```
`Radare2_ROOT` is a radare2 **install prefix** containing `include/libr/`
and `lib/`. CMake requires radare2 and builds the libr backend and plugin by
default; a missing radare2 installation is a configure error. The plugin is in
`build/bin/` (`build/bin/Release/` for the MSVC Release configuration).
`R2XSQL_BUILD_PLUGIN=OFF` disables the plugin target and
`R2XSQL_BUILD_EXAMPLES=OFF` disables examples. C++ consumers can embed the
library with `open_libr` and the `r2xsql_libr` target. 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`):
```bash
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 user-uninstall # remove the per-user plugin without building
make uninstall # remove the system-wide plugin without building
make test # load it in r2 and run one SQL query
# only `radare2` (not `r2`) on PATH? -> make R2=radare2
```
`make install` and `make uninstall` accept `PLUGDIR` and `DESTDIR` for a
custom plugin directory or staged install. User targets use `R2_USER_PLUGINS`;
override it on the make command line when needed.
Or with meson (what radare2 itself uses):
```bash
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`](https://github.com/0xeb/libxsql): the Makefile uses a
sibling `../libxsql` checkout (else clones it), and meson pulls it as a
subproject. All three builds pin the same libxsql release tag (`v1.0.21`).
Release assets are named `r2xsql-<radare2-version>-<R2PM_TRIPLET>.zip`, for
example `r2xsql-6.2.2-linux-x86-64.zip`. Each contains the plugin in `plugins/`.
With a recent r2pm supporting binary installs, use `r2pm -U` followed by
`r2pm -bi r2xsql`; uninstall with `r2pm -u r2xsql`. Only matching radare2
versions and targets are installed. To install manually, copy the plugin to
the directory printed by `radare2 -NN -H R2_USER_PLUGINS`.
### JSON results
Use `sqlj` for programmatic queries and scripts:
```text
"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
With the plugin installed, start r2's web server in a persistent session:
```sh
r2 -N -q \
-e http.bind=127.0.0.1 -e http.port=9090 -c aa -c '=h' ./target
```
Send a quoted SQL command through r2's `POST /cmd/` endpoint:
```sh
curl --data-binary '"sql SELECT name, size FROM funcs WHERE size > 100 LIMIT 5"' \
r2 -N -q -A -e scr.html=false -e http.bind=127.0.0.1 \
-e http.sandbox=false -e http.port=9090 -c '=h' ./target \
>r2.stdout.log 2>r2.stderr.log &
curl -d '"sqlj SELECT name,size FROM funcs ORDER BY size DESC LIMIT 10"' \
http://127.0.0.1:9090/cmd/
```
`GET /cmd/<encoded-command>` also works for short queries:
Wait for readiness before querying. r2's HTTP server carries SQL and native
commands; r2xsql has no separate server. Bind to loopback: this endpoint can
change analysis and write files. Reopen a saved project with `r2 -p PROJECT`
without `-A` or a separate binary argument. The [workflow guide](docs/usage.md)
covers Windows launches, saves, reopening, shutdown and HTTP version differences.
```python
from urllib.parse import quote
from urllib.request import urlopen
## Documentation
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.
`sql` executes one statement; `sqlj` executes a script and returns a JSON
envelope. The session persists between requests, including analysis and
comment changes.
Responses are native tables for `sql`, with no added row-count footer, or JSON
for `sqlj`. SQL errors can arrive with HTTP status 200: check `ERROR: ...` in
table output or `success` and per-statement errors in the JSON envelope. The old
`sql.http*` and `/query` interface is removed;
configure the native server with r2's `http.*` settings instead.
## Tests
Run the regression suite with radare2, `r2r`, a C compiler and Python 3 on
`PATH` (Python's standard library is used only for the HTTP transport test):
```sh
make test
```
This builds the plugin and runs the r2r database in `tests/db`. Each test loads
the exact build explicitly, ignoring installed user plugins, and checks its
output; SQL exceptions fail the suite even when radare2 exits successfully.
The fixture is compiled locally, with no downloaded test binaries or pytest.
To test an existing CMake/Meson build, or select matching radare2 tools:
```sh
make -C tests R2XSQL_PLUGIN=/absolute/path/core_r2xsql.so R2=/path/to/r2 R2R=/path/to/r2r
# Only command tests (no Python needed):
make -C tests TESTS=db/cmd
```
`R2R_ARGS` accepts r2r options (default `-L`); for example, `R2R_ARGS=-i` enables
interactive failure review. One small standard-library helper retains real
HTTP GET/POST coverage, including server startup and shutdown; r2r checks its
result alongside the command tests.
The Make build tracks header dependencies. This prevents stale adapters after
C++ interface changes, which could previously cause `std::bad_alloc` during
`make test`. After updating this Makefile, existing objects are rebuilt once
to establish dependency files. For older checkouts, `make clean && make test`
clears those stale objects.
## Backends (internal detail)
The plugin uses the host RCore; embedding and tests use these backends:
| Backend | Used by | Notes |
|---|---|---|
| `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. |
The in-process backend reads analysis, flags, symbols, binary metadata, IO maps,
write caches, types, and runtime catalogs through native libr APIs. The command
fallbacks support mock responses where needed. Instruction/operand text
rendering and byte/ROP searches still use radare2's command handlers to preserve
their rendering, search configuration, and hit behavior.
The internal r2pipe backend was for the removed standalone CLI and servers.
It duplicated process management and command-based access without serving the
native plugin, so it has been removed. External r2pipe clients can still send
`sql` commands to radare2 with this plugin loaded; radare2 also provides HTTP
access through `/cmd/`.
## 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`](https://github.com/radareorg/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.
- [User workflows and HTTP access](docs/usage.md)
- [SQL queries, formats and annotations](docs/sql.md)
- [Building, packaging and testing](docs/development.md)
- [Agent skills and schema reference](https://github.com/radareorg/radare2-skills/tree/main/r2xsql)
## License and Terms of Use
+126
View File
@@ -0,0 +1,126 @@
# Building and testing r2xsql
## Build
Linux / macOS:
```sh
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release \
-DRadare2_ROOT=/path/to/radare2/prefix
cmake --build build
```
Windows (MSVC):
```powershell
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 `
-DRadare2_ROOT=C:\path\to\radare2\prefix
cmake --build build --config Release
```
`Radare2_ROOT` is a radare2 **install prefix** containing `include/libr/`
and `lib/`. CMake requires radare2 and builds the libr backend and plugin by
default; a missing radare2 installation is a configure error. The plugin is in
`build/bin/` (`build/bin/Release/` for the MSVC Release configuration).
`R2XSQL_BUILD_PLUGIN=OFF` disables the plugin target and
`R2XSQL_BUILD_EXAMPLES=OFF` disables examples. C++ consumers can embed the
library with `open_libr` and the `r2xsql_libr` target. 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`):
```bash
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 user-uninstall # remove the per-user plugin without building
make uninstall # remove the system-wide plugin without building
make test # load it in r2 and run one SQL query
# only `radare2` (not `r2`) on PATH? -> make R2=radare2
```
`make install` and `make uninstall` accept `PLUGDIR` and `DESTDIR` for a
custom plugin directory or staged install. User targets use `R2_USER_PLUGINS`;
override it on the make command line when needed.
Or with meson (what radare2 itself uses):
```bash
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`](https://github.com/0xeb/libxsql): the Makefile uses a
sibling `../libxsql` checkout (else clones it), and meson pulls it as a
subproject. All three builds pin the same libxsql release tag (`v1.0.21`).
When published, binary release assets are named `r2xsql-<radare2-version>-<R2PM_TRIPLET>.zip`, for
example `r2xsql-6.2.4-linux-x86-64.zip`. Each contains the plugin in `plugins/`.
With a recent r2pm supporting binary installs, use `r2pm -U` followed by
`r2pm -bi r2xsql`; uninstall with `r2pm -u r2xsql`. Only matching radare2
versions and targets are installed. To install manually, copy the plugin to
the directory printed by `radare2 -NN -H R2_USER_PLUGINS`.
## Tests
Run the regression suite with radare2, `r2r`, a C compiler and Python 3 on
`PATH` (Python's standard library is used only for the HTTP transport test):
```sh
make test
```
This builds the plugin and runs the r2r database in `tests/db`. Each test loads
the exact build explicitly, ignoring installed user plugins, and checks its
output; SQL exceptions fail the suite even when radare2 exits successfully.
The fixture is compiled locally, with no downloaded test binaries or pytest.
To test an existing CMake/Meson build, or select matching radare2 tools:
```sh
make -C tests R2XSQL_PLUGIN=/absolute/path/core_r2xsql.so R2=/path/to/r2 R2R=/path/to/r2r
# Only command tests (no Python needed):
make -C tests TESTS=db/cmd
```
`R2R_ARGS` accepts r2r options (default `-L`); for example, `R2R_ARGS=-i` enables
interactive failure review. One small standard-library helper retains real
HTTP GET/POST coverage, including server startup and shutdown; r2r checks its
result alongside the command tests.
The Make build tracks header dependencies. This prevents stale adapters after
C++ interface changes, which could previously cause `std::bad_alloc` during
`make test`. After updating this Makefile, existing objects are rebuilt once
to establish dependency files. For older checkouts, `make clean && make test`
clears those stale objects.
## Backends (internal detail)
The plugin uses the host RCore; embedding and tests use these backends:
| Backend | Used by | Notes |
|---|---|---|
| `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. |
The in-process backend reads analysis, flags, symbols, binary metadata, IO maps,
write caches, types, and runtime catalogs through native libr APIs. The command
fallbacks support mock responses where needed. Instruction/operand text
rendering and byte/ROP searches still use radare2's command handlers to preserve
their rendering, search configuration, and hit behavior.
The internal r2pipe backend was for the removed standalone CLI and servers.
It duplicated process management and command-based access without serving the
native plugin, so it has been removed. External r2pipe clients can still send
`sql` commands to radare2 with this plugin loaded; radare2 also provides HTTP
access through `/cmd/`.
+73
View File
@@ -0,0 +1,73 @@
# SQL access
## Queries
For direct console use or programmatic clients:
```sql
SELECT name, size FROM funcs WHERE name LIKE 'main%';
SELECT content FROM strings WHERE content LIKE '%password%';
UPDATE comments SET text = 'reviewed' WHERE addr = 0x1234;
```
Tables read native analysis data or the JSON form of the relevant r2 command
(`aflj`, `izj`, `axtj`, …) from the host's in-process core.
## 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:
```sql
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 and reopen it with
`r2 -p NAME` without a separate binary or reanalysis. The plugin uses radare2's native project format; it does not
automatically save on exit.
Project save/open and full type declarations use native radare2 commands:
`Ps NAME`, `P NAME`, and `"td struct Header { int magic; };"`. The former SQL
functions `r2xsql_project_save`, `r2xsql_project_open`, and
`r2xsql_type_define` are removed. SQL can still list/delete projects and
create empty struct/union/enum types through the corresponding tables.
## Output formats
`sql` executes one statement using radare2's table renderer. It honours
`cfg.table.format`, `cfg.table.maxcol` and `scr.utf8`. Put a table query
immediately after `sql,`, before the SQL:
```text
sql,:csv SELECT name,size FROM funcs
sql,:tsv SELECT name,size FROM funcs
sql,?
```
Use SQL `WHERE`, `ORDER BY` and `LIMIT` for filtering. Table JSON (`sql,:json`)
omits NULL and empty-string cells; use `sqlj` for programmatic access.
`sql.tables` / `sql.views` discover the current schema; `sql.?` lists
subcommands. The `sql.` namespace does not carry SQL statements.
## JSON results
Use `sqlj` for programmatic queries and scripts:
```text
"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.
Read [saving and reopening](usage.md#saving-and-reopening) for persistence.
The same command works through r2pipe and radare2's HTTP `/cmd/` endpoint.
+231
View File
@@ -0,0 +1,231 @@
# Using r2xsql with radare2 and an agent
The plugin supplies SQL over a live radare2 core. The skills teach an agent
how to choose tables, query and annotate that core, and manage its lifetime.
The user can ask in natural language in either tandem or headless mode.
## Installation
Install radare2, then install a matching r2xsql plugin:
```sh
r2pm -U
r2pm -ci r2xsql
```
Installed plugins load automatically on normal startup. `make user-install`
does the same for a local build. Manual installation uses the directory
reported by `r2 -NN -H R2_USER_PLUGINS`. Restart a host after installation.
The plugin's radare2 ABI must match the engine loading it; iaito can use a
different engine from the standalone r2 on PATH. Binary installation with
`r2pm -bi r2xsql` requires an available asset matching the host and platform.
See [building and packaging](development.md).
For a build that is not installed:
```sh
r2 -i ./core_r2xsql.so -A ./target
```
Use the actual `.so`, `.dylib` or `.dll` file. `-i` also accepts native r2
command scripts. Inside an existing console, load a plugin with
`L ./core_r2xsql.so`; `L r2xsql` is not a package-name loader.
`-N` skips startup scripts while retaining plugins; `-NN` disables automatic
plugin loading too. For a deterministic local-build check, use `-NN -i FILE`.
Verify `r2xsql` in `Lcj`, then try `sql?` and `sqlj SELECT 1`.
Install the [r2xsql skills](https://github.com/radareorg/radare2-skills/tree/main/r2xsql#install)
in the coding agent's harness. Skills and the binary plugin are separate
installations. The harness selects the `r2xsql` entry skill and routes to
connection and domain instructions; explicit skill selection can be used
when the harness does not select it automatically.
## Tandem mode
Tandem shares an existing analysis in an interactive r2 CLI, its visual/panels
text interface, or [iaito](https://github.com/radareorg/iaito). For a fresh
binary run `r2 -A ./target`, or open it in iaito and let analysis finish.
For a saved project run `r2 -p PROJECT` without `-A`.
At the r2 prompt or iaito's **View > Console**, verify the plugin with `Lcj`,
then start background HTTP:
```text
e http.bind=127.0.0.1
e http.sandbox=false
e http.port=9090
=h&
```
Choose a free port. `http.port` selects it; `=h&` starts the background
server and leaves the console/UI available. It is an alias for `& =h`,
using r2's background-task facility. `=h` serves in the foreground instead.
Start HTTP at the prompt before entering the text interface.
Wait for `open http://127.0.0.1:9090/`, then tell the agent:
> Use r2xsql at http://127.0.0.1:9090 on the binary already open here.
> Show me the largest functions.
The agent checks the host, plugin and binary identity, authors SQL and reuses
the endpoint on later questions. It should not open another UI or rerun
analysis merely to attach. Renames and comments affect the human's analysis
too. Take turns with the agent when running analysis-changing native commands.
Use `=h-` at the interactive console to stop background HTTP while keeping
the human's host open.
For several hosts, select a distinct port per process and provide a mapping:
**application = http://127.0.0.1:9090, library = http://127.0.0.1:9091**.
The agent verifies each target and labels findings by source. SQL executes
inside one host; comparisons across hosts combine results in the client.
## Fully headless
With the plugin installed, an agent can start the native r2 process without
a human console or GUI. For a fresh binary, POSIX shell:
```sh
r2 -N -q -A -e scr.html=false -e http.bind=127.0.0.1 \
-e http.sandbox=false -e http.port=9090 -c '=h' ./target \
>r2.stdout.log 2>r2.stderr.log &
r2_pid=$!
```
Windows PowerShell:
```powershell
$engine = Get-Command r2,radare2 -CommandType Application -ErrorAction SilentlyContinue |
Select-Object -First 1
if (-not $engine) { throw 'Install radare2 or supply its executable location.' }
$target = (Resolve-Path -LiteralPath '.\target.exe').Path
$port = 9090 # choose a free port
$logDir = Join-Path $env:TEMP ('r2-session-' + [guid]::NewGuid().ToString('N'))
New-Item -ItemType Directory -Path $logDir | Out-Null
$arguments = '-N -q -A -e scr.html=false -e http.bind=127.0.0.1 -e http.sandbox=false -e http.port={0} -c "=h" "{1}"' -f $port,$target
$process = Start-Process -FilePath $engine.Source -ArgumentList $arguments -WindowStyle Hidden `
-RedirectStandardOutput (Join-Path $logDir 'stdout.log') `
-RedirectStandardError (Join-Path $logDir 'stderr.log') -PassThru
$endpoint = 'http://127.0.0.1:{0}/cmd/' -f $port
```
These launch radare2 directly. No Python session/query wrapper or build
orchestrator is needed. `-A` runs analysis once; foreground `=h` keeps the
background OS process alive. Queries use that same core until shutdown.
For an uninstalled plugin, substitute `-NN -i PLUGIN_FILE` for `-N`.
Wait for the server banner on stderr, then verify the endpoint with curl.
A bind failure is not readiness. Retain the PID, endpoint, binary/project
and log locations; subsequent prompts reuse this session.
## HTTP queries
For radare2 **6.2.4**, POST the complete r2 command to `/cmd/`:
```sh
curl -d '?V' http://127.0.0.1:9090/cmd/
curl -d 'Lcj' http://127.0.0.1:9090/cmd/
curl -d '"sqlj SELECT * FROM binary"' http://127.0.0.1:9090/cmd/
curl -d '"sqlj SELECT name,size FROM funcs WHERE size > 100 LIMIT 5"' \
http://127.0.0.1:9090/cmd/
```
In PowerShell use `curl.exe` to avoid the shell alias:
```powershell
$command = '"sqlj SELECT name,size FROM funcs ORDER BY size DESC LIMIT 10"'
curl.exe --silent --show-error --max-time 30 -d $command $endpoint
```
The body is an r2 command. The **double quotes are part of that body** and
protect SQL operators such as `>` and `|` from r2's parser. Use `sqlj`
for the JSON envelope; `sql,:json` is a table format with different NULL and
empty-string behavior. Inspect top-level and per-statement success/error
fields; HTTP 200 alone does not establish success. See [SQL access](sql.md).
Native commands such as `pdf` and `Ps` travel over the same endpoint.
The command-prefix-plus-body form is implemented in development radare2
and is planned for **6.2.6**:
```sh
curl -d 'SELECT name,size FROM funcs ORDER BY size DESC LIMIT 5' \
http://127.0.0.1:9090/cmd/sqlj
```
Here the URL selects `sqlj` and the body contains only SQL. This is a
version-dependent alternative, not a 6.2.4 example. Use the full-command
form until the host is known to support it. An agent should verify the JSON
response to a harmless query before choosing this form for mutations.
The combined command still passes through r2's parser. For SQL containing
operators such as `>` or `|`, keep the full double-quoted command form above.
## Saving and reopening
Analysis lives in memory until saved. Ask the agent to save the project beside
the binary, or select another location. The save operation is native radare2;
there is no SQL `save_database()` in r2xsql.
```sh
curl -d 'Ps /absolute/path/target.exe.r2' http://127.0.0.1:9090/cmd/
```
PowerShell, using the absolute target path from the launch:
```powershell
$project = ($target + '.r2').Replace('\','/')
curl.exe --silent --show-error --max-time 30 -d ('Ps ' + $project) $endpoint
Get-Item -LiteralPath $project
```
Use forward slashes in native r2 commands on Windows. Verify the actual saved
artifact, host log and requested annotations; a refused save can return an
empty HTTP 200. Keep the original binary and any companion `.r2.d` directory.
Saving analysis does not patch the executable or shut down the host.
Reopen the saved project with `-p`, without a separate target or reanalysis:
```sh
r2 -N -q -p /absolute/path/target.exe.r2 \
-e scr.html=false -e http.bind=127.0.0.1 \
-e http.sandbox=false -e http.port=9090 -c '=h' \
>r2.stdout.log 2>r2.stderr.log &
```
The project stores the binary path. On Windows replace `-A` and the target
in the launch arguments with `-p "PROJECT"`; keep the same `-e` options
and `-c "=h"`. Verify binary identity and saved annotations after reopening,
rather than checking only function counts. Preserve the checkpoint and logs
if verification fails.
### Projects and command scripts
Native projects support binary serialization and script compatibility; do not
infer their format from the filename alone. `Ps PROJECT` and `-p PROJECT`
are the normal save/reopen interface. A bare project name uses `dir.projects`;
an absolute filename selects a sidecar. `Pl` lists named projects, not every
sidecar elsewhere.
Where available, `prj?` documents the binary-container operations, including
`prj save FILE` and `prj open FILE`. Select the matching native loader for
an existing container; a standalone container is not interchangeable with a
named `-p` project on every host. Explicit command-script exports use `PS`
or `PS*` and can be interpreted with `-i SCRIPT`; they are not a reason to
describe all projects as scripts. Check `P?` and `prj?` on the chosen host.
## Shutdown and session ownership
On a save-and-shutdown request, save and verify first, then stop an agent-owned
foreground server:
```sh
curl 'http://127.0.0.1:9090/cmd/=h--'
```
`=h--` is intercepted in the GET path; putting it in a POST body does not
stop that accept loop. With the headless `-q` launch and no later commands,
r2 exits when serving ends. Verify the intended PID and listener stopped.
Do not close the user's tandem UI; stop its background server at the console
only when requested. Saving alone leaves the host available for follow-ups.
The server provides local command access, including writes when
`http.sandbox=false`. Bind to `127.0.0.1` and do not expose it as a public
service.
+8 -5
View File
@@ -112,22 +112,25 @@ if(WIN32)
NOMINMAX
_CRT_SECURE_NO_WARNINGS)
# On Windows the r2 import libs reference DLLs; copy them next to the full
# consumers (examples and core_r2xsql) so each loads radare2 without PATH
# juggling.
# Put the host DLLs beside embedding executables for both generator types.
if(Radare2_ROOT)
file(GLOB _r2_dlls "${Radare2_ROOT}/bin/*.dll")
if(_r2_dlls)
set(_r2_runtime_dest "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}")
if(CMAKE_CONFIGURATION_TYPES)
string(APPEND _r2_runtime_dest "/$<CONFIG>")
endif()
add_custom_target(r2xsql_copy_r2_dlls ALL
COMMAND ${CMAKE_COMMAND} -E make_directory
"${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>"
"${_r2_runtime_dest}"
VERBATIM)
foreach(_dll IN LISTS _r2_dlls)
add_custom_command(TARGET r2xsql_copy_r2_dlls POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${_dll}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>/"
"${_dll}" "${_r2_runtime_dest}/"
VERBATIM)
endforeach()
add_dependencies(r2xsql r2xsql_copy_r2_dlls)
endif()
endif()
endif()