R_ESIL(3) Library Functions Manual R_ESIL(3) NAME r_esil -- radare2 ESIL (Evaluable Strings Intermediate Language) library SYNOPSIS #include 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, emula- tion, and symbolic computation across different architectures. The core structure is REsil, which maintains a stack, registers, memory in- terfaces, 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) inter- faces; pass NULL,NULL for an anal-backed or standalone instance whose in- terfaces 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 ma- chine 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-termi- nated 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 inspect- ing 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 ana- lyzed 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-termi- nated 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 expres- sions. 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 de- bugging. 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_reg(3), r_io(3) GNU September 20, 2025 R_ESIL(3)