R_REG(3)
R_REG β the radare2 register management library π β¨
okay bestie, welcome to r_reg(3) from the Library Functions Manual, and no cap this one is the glow-up of register handling in radare2. grab a strawberry π and let's get into it.
SYNOPSIS
#include <r_reg.h>
DESCRIPTION
The r_reg API is a portable register model that gets used all over the place β analysis, emulation, debugging, the whole friend group. It hands you:
- typed register items β¨
- aliases, aka roles like PC/SP π
- an arena you can push/pop register snapshots on π
- helpers to read/write register values in all the different representations π¦
it's giving "one library to hold them all" fr fr.
INITIALIZATION
before you do literally anything, you need a register context. that context is the main character β it owns the profiles, the arena, and the register list. typical callers are the analysis engine and the debugger, and they each keep their own separate register contexts (no sharing bestie, they have their own vibes).
RReg * r_reg_new(void)β creates a new register context π«Άvoid r_reg_free(RReg *reg)β frees all the resources associated with the register context. bye bestie, you ate π
PROFILES
profiles are how the library knows which registers exist, how big they are, and what roles they play. they get loaded from strings or from files, and analysis + ESIL use them to map register names and roles. lowkey essential.
bool r_reg_set_profile(RReg *reg, const char *profile)β loads a profile from a file path πbool r_reg_set_profile_string(RReg *reg, const char *profile)β loads a profile straight from a string buffer πΈchar * r_reg_profile_to_cc(RReg *reg)β dumps the profile as C-compatible declarations (tools use this one) β¨
REGISTER ACCESS
register names and roles are the primary API for callers who just need scalar accesses. if you're out here needing float/double/packed values, go use the typed APIs instead (they're in the next section, don't worry).
RRegItem * r_reg_get(RReg *reg, const char *name, int type)β retrieve a register item by name; passtypeas-1to ignore type πut64 r_reg_getv(RReg *reg, const char *name)β get a 64-bit value for registername. this is the most common convenience function in the entire codebase (analysis, esil, debug all call it, it's iconic) π₯bool r_reg_setv(RReg *reg, const char *name, ut64 val)β set a 64-bit value for registername. ESIL and a bunch of other subsystems call this to do register writes π«Άut64 r_reg_get_value_by_role(RReg *reg, RRegAlias alias)β get the value of a register given its alias role (for exampleR_REG_ALIAS_PC). obsessed with this one when code works with roles instead of concrete names π
REGISTER VALUES
when you're dealing with non-integer registers (floating point, long double) or you're messing with sub-parts of registers, this is the section for you. typed getters/setters, let's gooo.
ut64 r_reg_get_value(RReg *reg, RRegItem *item)β return the integer value of a register itembool r_reg_set_value(RReg *reg, RRegItem *item, ut64 value)β set the integer value for a register itemfloat r_reg_get_float(RReg *reg, RRegItem *item)β get afloatvalue from the register item when applicabledouble r_reg_get_double(RReg *reg, RRegItem *item)β get adoublevalue from the register item when applicablelong double r_reg_get_longdouble(RReg *reg, RRegItem *item)β get a long double value (so useful for extended FP registers) πbool r_reg_set_longdouble(RReg *reg, RRegItem *item, long double value)β set a long double value in the register item
REGISTER LISTS
you can iterate registers by type β GPR, FPU, vector, flags. this is commonly used to serialize register state, or when you're emitting a register snapshot. very "packing my bags for a trip" energy π§
RList * r_reg_get_list(RReg *reg, int type)β return a list ofRRegItemfor the requested typeRRegItem * r_reg_index_get(RReg *reg, int idx)β get a register item by absolute index
ALIASES
aliases map roles to concrete register names, per profile β for example PC -> rip on x86_64. use these whenever your code should be architecture agnostic, because hard-coded register names are so not the vibe.
bool r_reg_alias_setname(RReg *reg, RRegAlias alias, const char *name)β assign a name to an alias roleconst char * r_reg_alias_getname(RReg *reg, RRegAlias alias)β return the concrete register name for the aliasconst char * r_reg_alias_tostring(RRegAlias alias)β return a textual representation of the alias role β¨
ARENA MANAGEMENT
the arena is literally the moment. it lets you temporarily change registers and restore them later, and it is heavily used by analysis passes and by debugger backends when they want to peek at or modify registers without permanently changing the user-visible state. peek, don't keep π«Ά
int r_reg_arena_push(RReg *reg)β push the current register snapshot onto the arena stack and return the new stack depthvoid r_reg_arena_pop(RReg *reg)β pop the last snapshot and restore register values to that state πut8 * r_reg_get_bytes(RReg *reg, int type, int *size)β get a packed byte representation of registers oftype(so good for copying to a target or computing diffs)bool r_reg_set_bytes(RReg *reg, int type, const ut8 *buf, const int len)β set the bytes for registers oftypefrom a buffer
CONDITIONS
these helpers convert CPU flags into boolean conditions (equal, greater, etc.) and back again. ESIL and analysis use them to evaluate branching conditions, so yeah, kind of a big deal.
bool r_reg_cond(RReg *r, int type)β evaluate a condition represented bytypeusing the current register flags. for example,R_REG_COND_EQchecks the zero flag πRRegFlags * r_reg_cond_retrieve(RReg *r, RRegFlags *f)β fill theRRegFlagsstructure from the current register flags (fields like zero, carry, sign) so callers can inspect or modify themvoid r_reg_cond_apply(RReg *r, RRegFlags *f)β apply aRRegFlagsstructure back into the register context
USAGE NOTES
the typical usage patterns you'll find in the codebase, bestie, are literally these:
- when analyzing or emulating instructions: push the arena, modify registers (for example set
PCto the next address), run the evaluation (ESIL or analysis) and pop the arena to restore the original state. files that follow this pattern includelibr/core/canal.candlibr/core/cmd_debug.inc.cπΈ - use
r_reg_getv/r_reg_setvfor most reads/writes, because they're simple and fast wrappers over the typed APIs. ESIL registers also callr_reg_setvthrough.reg_writehooks π₯ - when code needs to be architecture-agnostic, prefer
r_reg_get_value_by_roleorr_reg_alias_getnameinstead of hard-coded register names π
EXAMPLES
this example shows a common pattern used across radare2: read PC/SP, temporarily modify registers to simulate an instruction, and restore the previous state. iconic behaviour, no notes.
// obtain the register context from core
RReg *reg = core->anal->reg;
// read program counter and stack pointer
ut64 pc = r_reg_getv (reg, "PC");
ut64 sp = r_reg_getv (reg, "SP");
// create a temporary snapshot
r_reg_arena_push (reg);
// modify registers for analysis/emulation
r_reg_setv (reg, "PC", pc + insn_size);
// run evaluation or analysis using modified registers...
// restore previous register state
r_reg_arena_pop (reg);
another practical example β retrieving an alias value (role based):
// get program counter regardless of arch-specific name
ut64 pc = r_reg_get_value_by_role (reg, R_REG_ALIAS_PC);
ESIL integration note:
// ESIL uses r_reg_setv as the register write callback:
// in libr/esil/esil.c: .reg_write = (REsilRegWrite)r_reg_setv
// so using r_reg_setv keeps behavior consistent with ESIL expectations.
ngl that last one is the "iykyk" of this whole page. use r_reg_setv, stay consistent with ESIL, live your truth π
SEE ALSO
and that's the whole page bestie, you ate that π β¨ this one shipped as part of Debian, dated September 20, 2025 β go forth and manage some registers, you absolute icon ππ¦π
π¦ where this page comes from
- alpine 3.24: radare2-doc 6.1.6-r0 Β· GPL-3.0-or-later AND LGPL-2.0-or-later AND LGPL-2.1-or-later
- arch rolling: radare2 6.2.2-1 Β· GPL-3.0-only AND LGPL-3.0-only
- nixos 26.05: radare2 6.1.8
- nixpkgs unstable: radare2 6.2.4
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- opensuse-leap 16.0: radare2 6.2.2-bp160.1.1 Β· GPL-3.0-only AND LGPL-3.0-only
- ubuntu resolute: radare2 6.0.7+ds-1 Β· LGPL-3.0-only
- ubuntu stonking: radare2 6.1.8+ds-1 Β· LGPL-3.0-only
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms