Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
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)

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>

home | help