R_ARCH(3)
π R_ARCH β the architecture abstraction library for radare2 π
okay bestie, pull up a chair, this is the r_arch manual page (section 3, library functions manual) and it is lowkey a whole personality. grab a snack. π
β¨ 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 singleRArchperRCoreorRAnalinstance so the arch state (current plugin, esil, reg profile) is shared. πRArchConfigβ describes desired architecture parameters (name, bits, endianness, syntax). Set this before callingr_arch_useso the right plugin variant is selected.RAnalOpβ the container for decoded instruction information. Decoders fillop.size,op.mnemonic,op.esiland other fields depending on the decode mask. Consumers such as the ESIL executor rely onop.esilto obtain instruction semantics.RArchSessionβ per-plugin state allowing callers to directly invoke plugin callbacks (for example,plugin->regsto 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.
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_newand a configuration withr_arch_config_new. - Set desired options (
cfg->arch,cfg->bits,cfg->endian,cfg->syntax) and callr_arch_use (arch, cfg, name)to activate the plugin. - Query plugin capabilities via
r_arch_info(for exampleR_ARCH_INFO_MAXOP_SIZE), or create anRArchSessionwithr_arch_sessionwhen you need plugin callbacks, such asregs().
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.
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_sizebytes from the IO layer into a buffer. - Initialize and populate an
RAnalOpwithr_anal_op_initandr_anal_op_set_bytes. - Call
r_arch_decode (arch, &op, mask)with masks such asR_ARCH_OP_MASK_BASIC | R_ARCH_OP_MASK_ESILto obtain decoding and ESIL semantics. - On success inspect
op.size,op.esil,op.mnemonicand other fields and clean up withr_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_SIZEbytes (or a safe fallback) before callingr_arch_decode; plugins may require several bytes to decide instruction length. no cap, they really do need them π - Check
op.sizeandop.typeafter decoding. The core implementation uses hints (r_anal_hint_get) to overrideop.sizeorop.esilwhen available. - When decoding for emulation (ESIL) prefer to request ESIL with the
R_ARCH_OP_MASK_ESILmask so the plugin fillsop.esilwith 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.
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
RAnalOpwith the mnemonic (for example usingr_anal_op_set_mnemonic) and callr_arch_encodeto attempt encoding. - If the plugin cannot encode the instruction, query
r_arch_infofor fallback sizes:R_ARCH_INFO_INVOP_SIZE(size of an invalid instruction placeholder) orR_ARCH_INFO_CODE_ALIGNto 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().
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.
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.
bestie do NOT go anywhere, there's more of this page coming π
β¨ EXAMPLES β¨
okay bestie, here's where it all comes together π these are practical snippets adapted from core components, showing how decoding, ESIL integration and session usage vibe together to actually solve real tasks. no cap.
πΈ Example 1 β ESIL single-step πΈ
short sequence based on r_core_esil_single_step, let's go:
// 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);
like, step one: grab the max opcode size π and if that comes back less than 1, you just default it to 32. step two, read those bytes off the IO. step three, decode and specifically ask for ESIL with the mask combo. step four, peek at op.size and apply hints if you need them (the core does that with r_anal_hint_get), and if the size is under 1 or the type is R_ANAL_OP_TYPE_ILL, that's trap-handling territory π. then step five, run the ESIL expression (op.esil) in the REsil context. iconic.
π¦ Example 2 β load architecture register profile into core ESIL π¦
this one's from r_core_esil_load_arch, and it happens after arch/plugin/session are initialized:
// 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);
}
}
the way that this just checks the whole chain β session, plugin, and regs β before it even breathes π and then only sets the profile string if it actually got one back, and frees it like a responsible main character. periodt.
π SEE ALSO π
and that's the whole page, bestie!! π«Ά this one's from Debian, dated September 21, 2025, and it's R_ARCH(3) β go forth and decode responsibly β¨π
π
π¦ where this page comes from
- alpine 3.24: radare2-doc 6.1.6-r0 Β· GPL-3.0-or-later AND LGPL-2.0-or-later AND LGPL-2.1-or-later
- arch rolling: radare2 6.2.2-1 Β· GPL-3.0-only AND LGPL-3.0-only
- nixos 26.05: radare2 6.1.8
- nixpkgs unstable: radare2 6.2.4
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- ubuntu resolute: radare2 6.0.7+ds-1 Β· LGPL-3.0-only
- ubuntu stonking: radare2 6.1.8+ds-1 Β· LGPL-3.0-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms