Provided by: radare2_6.0.7+ds-1_amd64 bug

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)