FreeBSD Manual Pages
R_ARCH(3) Library Functions Manual R_ARCH(3) 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 plu- gin limits (e.g. maximum opcode size), run the generic decode/encode paths and to wrap plugin sessions when direct access to plugin callbacks is re- quired. Key concepts and why they matter in practice: * `RArch` a 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` a describes desired architecture parameters (name, bits, endianness, syntax). Set this before calling `r_arch_use` so the right plugin variant is selected. * `RAnalOp` a 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` a per-plugin state allowing callers to directly invoke plugin callbacks (for example, `plugin->regs` to obtain a register pro- file). 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 a for example ba- sic 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 sev- eral 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 in- struction 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 instruc- tion 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 ses- sion with `r_arch_session`. Sessions wrap a `RArchPlugin` and expose `ses- sion->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)` a query plugin-specific values. * `r_arch_session_preludes(session)` a 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 be- fore loading a plugin. Use `r_arch_config_set_bits`, `r_arch_con- fig_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 im- plementations 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 encod- ing. 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 num- bers instead of names when supported. EXAMPLES Below are practical snippets adapted from core components to show how de- coding, ESIL integration and session usage combine to solve real tasks. Example 1 a ESIL single-step (short sequence based on `r_core_esil_sin- gle_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 a 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) FreeBSD ports 15.quarterly September 21, 2025 R_ARCH(3)
NAME | SYNOPSIS | DESCRIPTION | INITIALIZATION | DECODING (DISASSEMBLING) | ENCODING (ASSEMBLING) | SESSIONS | CONFIGURATION | ARCHITECTURES | SYNTAX MODES | EXAMPLES | SEE ALSO
Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=r_arch&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>
