Provided by: radare2_6.0.7+ds-1_amd64 

NAME
r_arch — Architecture abstraction library for radare2
SYNOPSIS
The primary functions and types provided by the r_arch API are used to select architecture plugins,
configure decoding/encoding behaviour and create per-plugin sessions for advanced callbacks (for example
to fetch register profiles or run ESIL hooks). Use `r_arch_config_new` to create a configuration and
`r_arch_use` to activate an architecture plugin.
#include <r_arch.h>
DESCRIPTION
r_arch implements a thin, stable interface that core consumers (such as `libr/core` and `libr/anal`) use
to perform disassembly, assembly and to access plugin-specific capabilities. The API exposes helpers to
query plugin limits (e.g. maximum opcode size), run the generic decode/encode paths and to wrap plugin
sessions when direct access to plugin callbacks is required.
Key concepts and why they matter in practice:
• `RArch` — holds available arch plugins and an active session; most clients keep a single `RArch` per
`RCore` or `RAnal` instance so the arch state (current plugin, esil, reg profile) is shared.
• `RArchConfig` — describes desired architecture parameters (name, bits, endianness, syntax). Set this
before calling `r_arch_use` so the right plugin variant is selected.
• `RAnalOp` — the container for decoded instruction information. Decoders fill `op.size`,
`op.mnemonic`, `op.esil` and other fields depending on the decode mask. Consumers such as the ESIL
executor rely on `op.esil` to obtain instruction semantics.
• `RArchSession` — per-plugin state allowing callers to directly invoke plugin callbacks (for example,
`plugin->regs` to obtain a register profile). Use a session when you need functionality not exposed
by the generic decode/encode wrappers.
INITIALIZATION
Before decoding or encoding, create an `RArch` instance and configure the plugin you want to use. The
configuration controls bits, syntax and other plugin-specific options. Pp RArch * r_arch_new(void)
RArchConfig * r_arch_config_new(void)
void r_arch_config_free(RArchConfig *cfg)
bool r_arch_use(RArch *arch, RArchConfig *config, const char *name)
void r_arch_free(RArch *arch)
Typical initialization steps used across core components:
• Create an arch object with `r_arch_new` and a configuration with `r_arch_config_new`.
• Set desired options (`cfg->arch`, `cfg->bits`, `cfg->endian`, `cfg->syntax`) and call `r_arch_use
(arch, cfg, name)` to activate the plugin.
• Query plugin capabilities via `r_arch_info` (for example `R_ARCH_INFO_MAXOP_SIZE`), or create an
`RArchSession` with `r_arch_session` when you need plugin callbacks, such as `regs()`.
Example (typical init):
RArch *arch = r_arch_new();
RArchConfig *cfg = r_arch_config_new();
strcpy (cfg->arch, "x86");
cfg->bits = 64;
cfg->syntax = R_ARCH_SYNTAX_INTEL;
if (!r_arch_use (arch, cfg, "x86")) {
// handle error: requested plugin not available
}
// later
r_arch_config_free (cfg);
// r_arch_free (arch) when done
DECODING (DISASSEMBLING)
Decoding converts raw bytes to a populated `RAnalOp`. The API supports masks to control what information
the plugin should fill — for example basic fields, ESIL semantics or value operands. Real-world clients
first query the plugin for its maximum opcode length so they read enough bytes from IO. Pp int
r_arch_info(RArch *arch, int query)
bool r_arch_decode(RArch *a, RAnalOp *op, RArchDecodeMask mask)
void r_anal_op_init(RAnalOp *op)
bool r_anal_op_set_bytes(RAnalOp *op, ut64 addr, const ut8 *data, int size)
void r_anal_op_fini(RAnalOp *op)
Practical sequence used in `r_core_esil_single_step`:
• Query maximum opcode size: `r_arch_info (arch, R_ARCH_INFO_MAXOP_SIZE)`.
• Read up to `max_op_size` bytes from the IO layer into a buffer.
• Initialize and populate an `RAnalOp` with `r_anal_op_init` and `r_anal_op_set_bytes`.
• Call `r_arch_decode (arch, &op, mask)` with masks such as `R_ARCH_OP_MASK_BASIC |
R_ARCH_OP_MASK_ESIL` to obtain decoding and ESIL semantics.
• On success inspect `op.size`, `op.esil`, `op.mnemonic` and other fields and clean up with
`r_anal_op_fini`.
Minimal decode example (pattern taken from `r_core_esil_single_step`):
int max_op = r_arch_info (arch, R_ARCH_INFO_MAXOP_SIZE);
if (max_op < 1) { max_op = 32; }
ut8 buf[64];
if (!r_io_read_at (io, pc, buf, max_op)) {
// read failure
}
RAnalOp op;
r_anal_op_init (&op);
r_anal_op_set_bytes (&op, pc, buf, max_op);
if (!r_arch_decode (arch, &op, R_ARCH_OP_MASK_BASIC | R_ARCH_OP_MASK_ESIL)) {
r_anal_op_fini (&op);
// decode failed
}
// use op.size, op.esil, op.mnemonic ...
r_anal_op_fini (&op);
Notes and gotchas:
• Always ensure you read at least `R_ARCH_INFO_MAXOP_SIZE` bytes (or a safe fallback) before calling
`r_arch_decode`; plugins may require several bytes to decide instruction length.
• Check `op.size` and `op.type` after decoding. The core implementation uses hints (`r_anal_hint_get`)
to override `op.size` or `op.esil` when available.
• When decoding for emulation (ESIL) prefer to request ESIL with the `R_ARCH_OP_MASK_ESIL` mask so the
plugin fills `op.esil` with the instruction semantics.
ENCODING (ASSEMBLING)
Encoding converts textual mnemonics to machine code and populates the `RAnalOp` bytes. The common
workflow in `libr/anal` (see `r_anal_opasm`) first tries the encoder callback provided by the active
plugin/session and falls back to other encoders when necessary. Pp bool r_arch_encode(RArch *a, RAnalOp
*op, RArchEncodeMask mask)
RAnalOp * r_anal_op_new(void)
void r_anal_op_free(void *op)
bool r_anal_op_set_mnemonic(RAnalOp *op, ut64 addr, const char *s)
Key points:
• Prepare an `RAnalOp` with the mnemonic (for example using `r_anal_op_set_mnemonic`) and call
`r_arch_encode` to attempt encoding.
• If the plugin cannot encode the instruction, query `r_arch_info` for fallback sizes:
`R_ARCH_INFO_INVOP_SIZE` (size of an invalid instruction placeholder) or `R_ARCH_INFO_CODE_ALIGN` to
choose a reasonable number of bytes to reserve.
Encoding example (conceptual):
RAnalOp *op = r_anal_op_new ();
r_anal_op_set_mnemonic (op, 0, "mov rax, 42");
if (r_arch_encode (arch, op, 0)) {
// op->bytes and op->size now contain encoded data
} else {
int sz = r_arch_info (arch, R_ARCH_INFO_INVOP_SIZE);
if (sz < 1) sz = r_arch_info (arch, R_ARCH_INFO_CODE_ALIGN);
if (sz < 1) sz = 1;
// reserve `sz` bytes as fallback
}
r_anal_op_free (op);
SESSIONS
When you need direct access to plugin callbacks (for example to obtain a register profile string or to
use plugin-specific preludes), create a session with `r_arch_session`. Sessions wrap a `RArchPlugin` and
expose `session->plugin` which contains callbacks such as `regs()` or `esilcb()`. Pp RArchSession *
r_arch_session(RArch *arch, RArchConfig *cfg, RArchPlugin *ap)
int r_arch_session_info(RArchSession *as, int q)
RList * r_arch_session_preludes(RArchSession *as)
Real usage example from `r_core_esil_load_arch`:
// after activating arch and creating core->anal->arch->session
char *rp = core->anal->arch->session->plugin->regs (core->anal->arch->session);
if (rp) {
r_reg_set_profile_string (core->esil.reg, rp);
free (rp);
}
// the plugin may also register ESIL callbacks via session->plugin->esilcb
Other session helpers:
• `r_arch_session_info(session, q)` — query plugin-specific values.
• `r_arch_session_preludes(session)` — obtain RList of preludes injected by plugins (used by
disassemblers/emitters to add prologue code, etc.).
CONFIGURATION
`RArchConfig` and its helpers let you specify architecture attributes before loading a plugin. Use
`r_arch_config_set_bits`, `r_arch_config_set_cpu` and `r_arch_config_set_syntax` to set common options.
Plugins can read these fields when `r_arch_use` is called to select appropriate variants. Pp bool
r_arch_config_set_bits(RArchConfig *c, int bits)
void r_arch_config_set_cpu(RArchConfig *config, const char *cpu)
bool r_arch_config_set_syntax(RArchConfig *config, int syntax)
RArchConfig * r_arch_config_new(void)
void r_arch_config_free(RArchConfig *cfg)
Example: set CPU and syntax before calling `r_arch_use`:
r_arch_config_set_bits(cfg, 32);
r_arch_config_set_cpu(cfg, "cortex-a53");
r_arch_config_set_syntax(cfg, R_ARCH_SYNTAX_ATT);
r_arch_use(arch, cfg, NULL);
ARCHITECTURES
The architecture plugins are located under `libr/arch/p/*` and provide implementations for
decoders/encoders and ESIL callbacks. `r_arch_find` and `r_arch_use` select and activate a plugin by name
(plugins often use short names such as `x86`, `arm`, `mips`).
To discover which plugins were built inspect the `libr/arch/p` directory or call `r_arch_platform_list`
at runtime.
SYNTAX MODES
Some plugins support multiple syntax modes (for x86 this is commonly Intel or AT&T). The syntax
influences disassembly formatting and sometimes encoding. Set `cfg->syntax` with
`r_arch_config_set_syntax` before calling `r_arch_use`.
Common syntax constants are `R_ARCH_SYNTAX_INTEL`, `R_ARCH_SYNTAX_ATT` and `R_ARCH_SYNTAX_MASM`. Use
`R_ARCH_SYNTAX_REGNUM` to request register numbers instead of names when supported.
EXAMPLES
Below are practical snippets adapted from core components to show how decoding, ESIL integration and
session usage combine to solve real tasks.
Example 1 — ESIL single-step (short sequence based on `r_core_esil_single_step`):
// 1. get max opcode size
int max_op = r_arch_info (arch, R_ARCH_INFO_MAXOP_SIZE);
if (max_op < 1) { max_op = 32; }
// 2. read bytes from IO
ut8 buf[64];
if (!r_io_read_at (io, pc, buf, max_op)) { /* read error */ }
// 3. decode requesting ESIL
RAnalOp op; r_anal_op_init (&op);
r_anal_op_set_bytes (&op, pc, buf, max_op);
if (!r_arch_decode (arch, &op, R_ARCH_OP_MASK_BASIC | R_ARCH_OP_MASK_ESIL)) {
r_anal_op_fini (&op);
// decode failed or unknown instruction
}
// 4. check op.size and apply hints if needed (core uses r_anal_hint_get)
if (op.size < 1 || op.type == R_ANAL_OP_TYPE_ILL) { /* trap handling */ }
// 5. run ESIL expression (op.esil) in the REsil context
char *esil_expr = r_strbuf_drain_nofree (&op.esil);
// r_esil_parse(core_esil, esil_expr);
free (esil_expr);
r_anal_op_fini (&op);
Example 2 — load architecture register profile into core ESIL (from `r_core_esil_load_arch`):
// after arch/plugin/session are initialized
if (core->anal->arch->session && core->anal->arch->session->plugin &&
core->anal->arch->session->plugin->regs) {
char *reg_profile = core->anal->arch->session->plugin->regs (
core->anal->arch->session);
if (reg_profile) {
r_reg_set_profile_string (core->esil.reg, reg_profile);
free (reg_profile);
}
}
SEE ALSO
r_anal(3), r_asm(3), r_core(3)
Debian September 21, 2025 R_ARCH(3)