---
name: "r_esil"
section: "3"
platform: "linux"
package: "radare2"
version: "6.2.2-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/r_esil"
---

# r\_esil(3)

radare2 ESIL (Evaluable Strings Intermediate Language) library

## NAME

**r\_esil** – radare2 ESIL (Evaluable Strings Intermediate Language) library

## SYNOPSIS

**#include \<r\_esil.h\>**

## DESCRIPTION

The **r\_esil** library implements ESIL, a stack-based intermediate language for symbolic execution and emulation in radare2. ESIL allows for architecture-independent representation of CPU instructions, enabling analysis, emulation, and symbolic computation across different architectures.

The core structure is *REsil*, which maintains a stack, registers, memory interfaces, and operation handlers for executing ESIL expressions.

## INITIALIZATION

Create and configure ESIL contexts and their runtime dependencies so they are ready for parsing, execution and interaction with radare2 analysis and I/O layers.

*REsilOptions* **r\_esil\_options**(*void \*reg*, *void \*iob*)

Returns a stack-allocated REsilOptions struct prefilled with sane defaults (stacksize 4096, no iotrap, 64bit addresses). When reg and/or iob are passed they bind the simple register (RReg) and memory (RIOBind) interfaces; pass NULL,NULL for an anal-backed or standalone instance whose interfaces are wired later by r\_esil\_setup. Tweak the returned struct's fields before handing it to a constructor.

*REsil* *\** **r\_esil\_new**(*REsilOptions \*opt*)

Allocates and initializes a new ESIL instance from the given options (or built-in defaults when opt is NULL).

*bool* **r\_esil\_init**(*REsil \*esil*, *REsilOptions \*opt*)

Initializes a caller-owned ESIL structure in place from the given options. Any interface that has a user pointer but no callbacks is filled with the default implementations.

*void* **r\_esil\_free**(*REsil \*esil*)

Frees all resources associated with the ESIL instance.

## PARSING AND EXECUTION

Convert ESIL strings into runtime operations and drive the ESIL virtual machine to evaluate or emulate instruction semantics; these routines are the entry points for feeding ESIL expressions into the engine.

*bool* **r\_esil\_parse**(*REsil \*esil*, *const char \*str*)

Parses and executes an ESIL expression string.

*bool* **r\_esil\_runword**(*REsil \*esil*, *RStrs word*)

Executes a single ESIL operation word given as a slice. Wrap a NUL-terminated C string with **r\_strs\_from**() (or **R\_STRS\_LIT**() for literals) to run it.

## STACK OPERATIONS

Manipulate the ESIL evaluation stack directly when constructing or inspecting temporary values used during expression evaluation.

*bool* **r\_esil\_push**(*REsil \*esil*, *RStrs s*)

Pushes a value or expression onto the ESIL stack as a slice. Wrap a NUL-terminated C string with **r\_strs\_from**() (or **R\_STRS\_LIT**() for literals) to push it.

*RStrs* **r\_esil\_pop**(*REsil \*esil*)

Pops the top value from the ESIL stack as a slice.

*bool* **r\_esil\_pushnum**(*REsil \*esil*, *ut64 num*)

Pushes a numeric value onto the stack.

## REGISTER ACCESS

Query and modify the register state the ESIL engine uses; these functions bridge ESIL and the radare2 register model (RReg) and are used extensively by core components to read/write CPU state silently or with callbacks.

*bool* **r\_esil\_reg\_read**(*REsil \*esil*, *const char \*regname*, *ut64 \*val*, *ut32 \*size*)

Reads the value of a register.

*bool* **r\_esil\_reg\_write**(*REsil \*esil*, *const char \*name*, *ut64 val*)

Writes a value to a register.

## MEMORY ACCESS

Read from and write into the memory backing used by ESIL. Implementations may use the radare2 I/O bindings so ESIL memory operations map to the analyzed process or file backend.

*bool* **r\_esil\_mem\_read**(*REsil \*esil*, *ut64 addr*, *ut8 \*buf*, *int len*)

Reads memory at the specified address.

*bool* **r\_esil\_mem\_write**(*REsil \*esil*, *ut64 addr*, *const ut8 \*buf*, *int len*)

Writes data to memory at the specified address.

## OPERATIONS

Register, query or remove ESIL operation handlers. Custom operations can be installed to extend or override built-in ESIL semantics at runtime.

*bool* **r\_esil\_set\_op**(*REsil \*esil*, *const char \*op*, *REsilOpCb code*, *ut32 push*, *ut32 pop*, *ut32 type*, *const char \*info*)

Defines a custom ESIL operation.

*REsilOp* *\** **r\_esil\_get\_op**(*REsil \*esil*, *RStrs w*)

Retrieves information about an ESIL operation by slice. Wrap a NUL-terminated C string with **r\_strs\_from**() (or **R\_STRS\_LIT**() for literals) to look it up.

## PLUGINS

Manage architecture or feature plugins which provide arch-specific ESIL initialization, helpers and extra op handlers; activating a plugin hooks it into the ESIL instance used by analysis and emulation.

*bool* **r\_esil\_plugin\_add**(*REsil \*esil*, *REsilPlugin \*plugin*)

Adds an ESIL plugin for architecture-specific operations.

*bool* **r\_esil\_plugin\_activate**(*REsil \*esil*, *const char \*name*)

Activates an ESIL plugin by name.

## TRACING

Record and inspect execution traces produced while ESIL evaluates expressions. The trace subsystem captures ops, memory and register accesses to aid analysis and debugging of emulation sessions.

*REsilTrace* *\** **r\_esil\_trace\_new**(*REsil \*esil*)

Creates a new trace for recording ESIL execution.

*void* **r\_esil\_trace\_op**(*REsil \*esil*, *struct r\_anal\_op\_t \*op*)

Traces the execution of an analysis operation.

## INTERRUPTS AND SYSCALLS

Install handlers or trigger software interrupts and syscalls from ESIL; these hooks allow embedding environment-specific behavior (e.g. syscalls emulation) into ESIL evaluation.

*bool* **r\_esil\_set\_interrupt**(*REsil \*esil*, *ut32 intr\_num*, *REsilHandlerCB cb*, *void \*user*)

Sets a handler for a specific interrupt number.

*bool* **r\_esil\_set\_syscall**(*REsil \*esil*, *ut32 sysc\_num*, *REsilHandlerCB cb*, *void \*user*)

Sets a handler for a specific syscall number.

## COMPILER

Provide utilities to translate or compile ESIL expressions into other forms such as C-like code (esil-\>c) and to reuse ESIL parsing logic outside a running engine.

*REsilCompiler* *\** **r\_esil\_compiler\_new**(*void*)

Creates a new ESIL compiler for converting expressions.

*bool* **r\_esil\_compiler\_parse**(*REsilCompiler \*ec*, *const char \*expr*)

Parses an ESIL expression into the compiler.

## EXAMPLES

Show how to wire ESIL to minimal register and memory callbacks to evaluate an expression and retrieve the result, plus a compact low-level example that demonstrates direct stack manipulation and simple expression-level debugging.

Full example: set up register and memory callbacks, evaluate an ESIL string, and read the result:

```
/* Simple register callbacks that only handle "rax" and "rbx" for demo */
static bool my_is_reg(void *user, const char *name) {
    return !strcmp(name, "rax") || !strcmp(name, "rbx");
}
static bool my_reg_read(void *user, const char *name, ut64 *res) {
    if (!strcmp(name, "rax")) { *res = 0x10; return true; }
    if (!strcmp(name, "rbx")) { *res = 0x20; return true; }
    return false;
}
static bool my_reg_write(void *user, const char *name, ut64 val) {
    /* store val into your backend */
    (void)user; (void)name; (void)val; return true;
}
static ut32 my_reg_size(void *user, const char *name) { (void)user; (void)name; return 64; }
/* Simple memory callbacks using a flat buffer */
static ut8 my_mem[0x10000];
static bool my_mem_read(void *user, ut64 addr, ut8 *buf, int len) {
    memcpy (buf, my_mem + addr, len); return true;
}
static bool my_mem_write(void *user, ut64 addr, const ut8 *buf, int len) {
    memcpy (my_mem + addr, buf, len); return true;
}
int main(void) {
    REsilRegInterface reg_if = { .reg = NULL, .is_reg = my_is_reg, .reg_read = my_reg_read, .reg_write = my_reg_write, .reg_size = my_reg_size };
    REsilMemInterface mem_if = { .mem = NULL, .mem_read = my_mem_read, .mem_write = my_mem_write };
    REsilOptions opt = r_esil_options (NULL, NULL);
    opt.stacksize = 128;
    opt.ifaces.reg = reg_if;
    opt.ifaces.mem = mem_if;
    REsil *esil = r_esil_new (&opt);
    if (!esil) return -1;
    // Evaluate an expression that reads RAX, adds 8 and leaves the result on the stack
    r_esil_parse (esil, "rax,8,+");
    // Pop the result as a slice (arena-backed, no free needed)
    RStrs res = r_esil_pop (esil);
    if (!r_strs_empty (res)) {
        printf ("esil result: %s0, res.a);
    }
    r_esil_free (esil);
    return 0;
}
```

Low-level example: push/pop and expression-level debugging similar to the esil debugger (show stack, run a single operation):

```
REsilOptions opt = r_esil_options (NULL, NULL);
opt.stacksize = 32;
REsil *esil = r_esil_new (&opt);
// push two numbers, run the '+' op and inspect the result
r_esil_pushnum (esil, 2);
r_esil_pushnum (esil, 3);
// run the '+' word directly (same as parsing "2,3,+")
r_esil_runword (esil, R_STRS_LIT ("+"));
RStrs sum = r_esil_pop (esil);
printf ("2 + 3 = %s0, sum.a);
// dump stack state (useful when interactively debugging expressions)
r_esil_dumpstack (esil);
r_esil_free (esil);
```

## SEE ALSO

[r\_anal(3)](/r_anal/3.md), [r\_reg(3)](/r_reg/3.md), [r\_io(3)](/r_io/3.md)
