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

FreeBSD Manual Pages

  
 
  

home | help
R_DEBUG(3)		     Library Functions Manual		      R_DEBUG(3)

NAME
     r_debug -- radare2 debugger library

SYNOPSIS
     #include <r_debug.h>

DESCRIPTION
     The r_debug library provides debugging capabilities for radare2, supporting
     process  attachment,  stepping,  breakpoints, register manipulation, memory
     inspection, and various debugging operations across different platforms and
     architectures.

     The core structure is RDebug, which manages debugger state, plugins, break-
     points, registers, and process information.

INITIALIZATION
     RDebug * r_debug_new(int hard)

     Creates and returns a new debugger context. Use this as the first step when
     writing code that drives the debugger programmatically. The optional `hard`
     parameter enables hardware-specific  debugging  features  (when  available)
     such  as  hardware breakpoints. Typical usage is to create the context with
     `r_debug_new ()`, configure the `RDebug` fields (for  example  setting  the
     core  pointer or event hooks), then call `r_debug_start ()` or `r_debug_at-
     tach ()` to begin debugging.

     Always free the returned object with `r_debug_free ()`  once  debugging  is
     finished to avoid leaking resources.

     void r_debug_free(RDebug *dbg)

     Frees  all resources associated with the debugger context and its substruc-
     tures. After calling this function the `RDebug *` must not be used. Typical
     pattern:

	   RDebug *dbg = r_debug_new (0);
	   // configure dbg->coreb.core, dbg->anal, etc.
	   // attach or start target
	   // debug loop
	   r_debug_free (dbg);

PROCESS CONTROL
     bool r_debug_attach(RDebug *dbg, int pid)

     Attach to an existing process and prepare the internal plugin and IO  call-
     backs  for  controlling  the  target. After a successful attach you usually
     call `r_debug_reg_sync (dbg, R_REG_TYPE_GPR, false)` to  populate	register
     state  and  `r_debug_bp_update  (dbg)`  if  breakpoints need to be resolved
     against symbol expressions. When attaching to remote  backends  the  plugin
     selected  (the  `dbg->current->plugin`)  determines the behaviour of `r_de-
     bug_attach ()` and subsequent I/O.

     bool r_debug_detach(RDebug *dbg, int pid)

     Detach the debugger from the target process. Use  this  when  you	want  to
     leave  the  debuggee running under its own control. After detaching you may
     still call `r_debug_info ()` to read cached information, but  most  control
     functions will no longer be available.

     bool r_debug_start(RDebug *dbg, const char *cmd)

     Start  and  spawn	a new process for debugging with the given command. This
     sets up the debugging plugin's process creation  flow  (for  example  using
     `fork/exec`  on  native backends or a remote protocol for remote backends).
     After `r_debug_start ()` the usual flow is to call `r_debug_wait ()` to ob-
     serve the initial stop event, then set breakpoints and continue.

EXECUTION CONTROL
     int r_debug_step(RDebug *dbg, int steps)

     Perform one or more single instruction steps on the  selected  thread.  Use
     `r_debug_step ()` for instruction-level stepping. For higher-level stepping
     that  steps  over function calls use `r_debug_step_over ()`. If you need to
     execute until a given address use `r_debug_continue_until ()`.

     When stepping after hitting a software breakpoint, the library handles  the
     "recoil"  process	(clearing  the	breakpoint, stepping once, restoring the
     breakpoint). Callers do not normally need to implement recoiling themselves
     but should be aware that `r_debug_step ()` may return a value less than re-
     quested when a breakpoint was involved.

     int r_debug_step_over(RDebug *dbg, int steps)

     Step over function calls for `steps` instructions. This is useful when  im-
     plementing  source-level stepping or when the caller wants to skip stepping
     into library code.

     int r_debug_continue(RDebug *dbg)

     Resume execution until the debuggee stops due to a  breakpoint,  signal  or
     other  event.  Before  calling  `r_debug_continue	()` ensure that software
     breakpoints are properly restored by calling `r_debug_bp_update ()` if  you
     modified  breakpoint  expressions,  and sync registers if you modified them
     locally. For multi-threaded targets prefer using the `continue_all_threads`
     flag on `RDebug` when supported by the backend.

     bool r_debug_continue_until(RDebug *dbg, ut64 addr)

     Resume execution and stop when the program counter reaches `addr`. This  is
     convenient  for  implementing  temporary  range  stepping:  add a temporary
     breakpoint with `r_debug_bp_add ()` and then call `r_debug_continue ()`, or
     use `r_debug_continue_until ()` to  avoid	explicit  breakpoint  management
     when supported by the plugin.

WAITING AND REASONS
     RDebugReasonType r_debug_wait(RDebug *dbg, RBreakpointItem **bp)

     Block  until  the	debuggee  stops and return the reason (an `RDebugReason-
     Type`).  `r_debug_wait ()` is the canonical way to  implement  a  debugging
     loop:  call it after `r_debug_continue ()` or `r_debug_step ()` and inspect
     the returned reason via `r_debug_stop_reason ()` or by testing  the  return
     value. If `bp` is non-NULL and the stop reason involves a breakpoint, `*bp`
     will be set to the `RBreakpointItem *` that was hit.

     Typical usage pattern:

	   r_debug_continue (dbg);
	   RBreakpointItem *bp = NULL;
	   RDebugReasonType why = r_debug_wait (dbg, &bp);
	   if (why == R_DEBUG_REASON_BREAKPOINT && bp) {
	       // inspect registers and memory here
	   }

     RDebugReasonType r_debug_stop_reason(RDebug *dbg)

     Return  the  last	stop reason stored in `dbg->reason`. This is useful when
     you cannot block on `r_debug_wait ()` (for example when integrating with an
     event loop) and need to poll the current state.

     const char * r_debug_reason_tostring(int type)

     Return a human-readable string for the given reason code. Useful  for  log-
     ging or user-facing messages when reporting why a debuggee stopped.

REGISTER MANAGEMENT
     bool r_debug_reg_sync(RDebug *dbg, int type, int write)

     Synchronize registers between the local `RReg` view and the debuggee.  Call
     with  `write  ==  false` to read registers from the debuggee into the local
     `RReg` and with `write == true` to push local register values into the  de-
     buggee.  Always  call `r_debug_reg_sync (dbg, R_REG_TYPE_GPR, false)` after
     attaching to ensure that `r_debug_reg_get ()` returns meaningful values.

     ut64 r_debug_reg_get(RDebug *dbg, const char *name)

     Return the value of the register named `name` using the local `RReg` cache.
     This value is only as up-to-date as the last `r_debug_reg_sync ()`.

     bool r_debug_reg_set(RDebug *dbg, const char *name, ut64 num)

     Set a register locally. After  calling  `r_debug_reg_set  ()`  call  `r_de-
     bug_reg_sync  (dbg,  R_REG_TYPE_GPR,  true)` to write the change to the de-
     buggee. Common pattern: read PC with `r_debug_reg_get ()`, update a  regis-
     ter, write back with `r_debug_reg_sync ()`, then `r_debug_continue ()`.

     bool  r_debug_reg_list(RDebug  *dbg,  int	type, int size, PJ *pj, int rad,
     const char *use_color)

     Produce a formatted list of registers suitable for printing. Useful for im-
     plementing `info registers` style commands in front-ends.

BREAKPOINTS
     RBreakpointItem * r_debug_bp_add(RDebug  *dbg,  ut64  addr,  int  hw,  bool
     watch, int rw, char *module, st64 m_delta)

     Add  a breakpoint at `addr`. Use `hw` to request a hardware breakpoint when
     supported by the backend, `watch` to indicate  a  watchpoint  and	`rw`  to
     specify  read/write  conditions for watchpoints. `module` and `m_delta` are
     used for module-relative expressions. After adding breakpoints call  `r_de-
     bug_bp_update ()` to resolve expression-based breakpoints and make sure the
     plugin has the correct breakpoint list loaded.

     The  library  distinguishes  software  and  hardware  breakpoints: software
     breakpoints are typically implemented by writing a trap instruction to  the
     target  process and therefore must be temporarily removed when the debugger
     needs to execute target code (for example when implementing recoil).  Hard-
     ware  breakpoints do not require patching memory but are usually limited in
     number.

     void r_debug_bp_update(RDebug *dbg)

     Resolve breakpoint expressions  and  update  the  internal  breakpoint  ad-
     dresses.  Call this after adding breakpoints by name/expression. The imple-
     mentation calls `r_bp_get_at ()` and `r_bp_restore ()` internally to manage
     software breakpoints; front-ends should not duplicate that logic.

MEMORY MANAGEMENT
     RList * r_debug_map_list_new(void)

     Create an empty list used to store memory map entries (the same format used
     by `r_debug_map_get ()`). Use this to enumerate memory regions when  imple-
     menting memory listing or to build a synthetic map for analysis.

     RDebugMap * r_debug_map_get(RDebug *dbg, ut64 addr)

     Return  the  `RDebugMap`  corresponding  to the memory region that contains
     `addr`. The returned map is owned by the `RDebug` internals; callers should
     not free it directly. Use `r_debug_map_protect ()` to change memory protec-
     tions for writable patching or to make a region executable for `r_debug_ex-
     ecute ()`.

     bool r_debug_map_protect(RDebug *dbg, ut64 addr, int size, int perms)

     Change memory protection for a region starting at `addr`.	This  is  useful
     when you want to write code into the target and execute it (for example for
     trampolines).  Many  backends  require cooperation with the plugin, and the
     call will fail if the underlying OS does not permit the kind of change  re-
     quested.

PROCESS INFORMATION
     RDebugInfo * r_debug_info(RDebug *dbg, const char *arg)

     Query  miscellaneous  information	about  the debugged process, such as its
     current working directory, command line and executable path. Backends popu-
     late this structure from platform-specific sources; it  is  convenient  for
     front-ends that need to show process metadata.

     void r_debug_info_free(RDebugInfo *rdi)

     Free the `RDebugInfo` structure returned by `r_debug_info ()`.

THREADS AND PROCESSES
     RList * r_debug_pids(RDebug *dbg, int pid)

     Return  a	list of process/thread identifiers that the backend knows about.
     Use this to implement thread list UIs. Each list element  is  typically  an
     `RDebugPid` or similar structure depending on the plugin.

     bool r_debug_select(RDebug *dbg, int pid, int tid)

     Select  a	specific process and thread (if supported) for subsequent opera-
     tions. After selecting a thread, calls like  `r_debug_step  ()`  or  `r_de-
     bug_reg_sync  ()`	operate  on the selected thread. Remember to call `r_de-
     bug_reg_sync ()` after switching threads to refresh register state.

SIGNALS
     int r_debug_signal_send(RDebug *dbg, int num)

     Send the signal `num` to the debuggee. This can be used to emulate user ac-
     tions such as `SIGINT` or to forward signals from a front-end.

     int r_debug_signal_resolve(RDebug *dbg, const char *signame)

     Resolve a textual signal name like "SIGINT" to its numeric value.

     const char * r_debug_signal_resolve_i(RDebug *dbg, int signum)

     Return the canonical name for `signum` (for example, `SIGSEGV`). Useful for
     logging and user messages.

TRACING
     RDebugTrace * r_debug_trace_new(void)

     Create and initialize a trace context used by the tracing facilities in the
     debugger. The trace APIs provide a way to record program execution  history
     (PCs, memory snapshots) for later analysis.

     void r_debug_trace_free(RDebugTrace *dbg)

     Free a trace context created with `r_debug_trace_new ()`.

     RDebugTracepointItem * r_debug_trace_add(RDebug *dbg, ut64 addr, int size)

     Add  a  tracepoint  at  `addr`.  When  the tracepoint is hit the tracer may
     record state according to the trace configuration.

PLUGINS
     bool r_debug_plugin_add(RDebug *dbg, RDebugPlugin *plugin)

     Register a debugger plugin implementation with the `RDebug` instance.  Plu-
     gins implement architecture/OS-specific behaviour such as process	control,
     register  IO  and	memory access. The built-in backends (native, gdb, etc.)
     are provided as plugins; front-ends can add custom plugins to support addi-
     tional transports.

     bool r_debug_plugin_remove(RDebug *dbg, RDebugPlugin *plugin)

     Unregister a previously added plugin. Removing the current plugin while de-
     bugging is not supported and will typically fail.

EXECUTION
     bool r_debug_execute(RDebug *dbg, const ut8 *buf, int len, ut64 *ret,  bool
     restore, bool ignore_stack)

     Execute  the  machine  code  in  `buf`  of length `len` inside the debugged
     process and optionally return a value via `ret`. If `restore` is  true  the
     original  memory  contents and registers are restored after execution.  The
     `ignore_stack` flag lets the plugin adjust stack-related safety checks when
     injecting code. This function is useful to evaluate small snippets  in  the
     target process for dynamic analysis or for implementing functions that need
     to run in the target context.

DEBUG REASONS
     The library defines various reasons why a debuggee might stop:

     R_DEBUG_REASON_BREAKPOINT	Hit a breakpoint

     R_DEBUG_REASON_SIGNAL	Received a signal

     R_DEBUG_REASON_STEP	Completed a step

     R_DEBUG_REASON_SEGFAULT	Segmentation fault

EXAMPLES
     The  examples  below  show  common  real-world sequences found in radare2's
     front-ends and plugins. They assume a native backend but the same	patterns
     apply to remote backends via their plugin implementations.

     Minimal attach-and-continue loop:

	   RDebug *dbg = r_debug_new (0);
	   // attach and populate registers
	   if (!r_debug_attach (dbg, pid)) {
	       // handle error
	   }
	   if (!r_debug_reg_sync (dbg, R_REG_TYPE_GPR, false)) {
	       // cannot read registers
	   }
	   // set a breakpoint at a symbol or address
	   RBreakpointItem *bp = r_debug_bp_add (dbg, 0x400000, 0, false, 0, NULL, 0);
	   r_debug_bp_update (dbg);
	   // resume and wait for events
	   r_debug_continue (dbg);
	   RBreakpointItem *hit = NULL;
	   RDebugReasonType why = r_debug_wait (dbg, &hit);
	   if (why == R_DEBUG_REASON_BREAKPOINT && hit) {
	       ut64 pc = r_debug_reg_get (dbg, "PC");
	       // inspect/modify registers or memory
	   }

     Step-and-inspect example (useful for implementing a step debugger):

	   RDebug *dbg = r_debug_new (0);
	   // start or attach
	   r_debug_step (dbg, 1);
	   if (r_debug_wait (dbg, NULL) == R_DEBUG_REASON_STEP) {
	       // make sure registers are synced
	       r_debug_reg_sync (dbg, R_REG_TYPE_GPR, false);
	       ut64 sp = r_debug_reg_get (dbg, "SP");
	       // read memory via dbg->iob.read_at or use r_debug_map_get to find protections
	   }

     Executing injected snippets safely:

	   // prepare the small machine code to run (architecture dependent)
	   const ut8 code[] = { 0x90, 0x90 }; // nop; nop
	   ut64 ret = 0;
	   if (r_debug_execute (dbg, code, sizeof (code), &ret, true, false)) {
	       // result available in ret
	   }

SEE ALSO
     r_bp(3), r_reg(3), r_anal(3)

FreeBSD ports 15.quarterly     September 20, 2025		      R_DEBUG(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=r_debug&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help