Chapter 20: Debugger

The debugger in radare is implemented as an IO plugin. It handles two different URIs for creating or attaching to a process: dbg:// and pid://.

There are different backends for multiple architectures and operating systems like GNU/Linux, Windows, MacOSX, (Net,Free,Open)BSD and Solaris.

The process memory is interpreted by radare as a plain file. So all the mapped pages like the program and the libraries can be readed and interpreted as code, structures, etc..

The rest of the communication between radare and the debugger layer is the wrapped system() call that receives a string as argument and executes the given command. The result of the operation is buffered in the output console and this contents can be handled by a scripting language.

This is the reason why radare can handle single and double exclamation marks for calling system().

[0x00000000]> !step
[0x00000000]> !!ls

The double exclamation mark tells radare to skip the plugin list to find an IO plugin handling this command to launch it directly to the shell. A single one will walk thru the io plugin list.

The debugger commands are mostly portable between architectures and operating systems. But radare tries to implement them on all the artchitectures and OSs injecting shellcodes, or handling exceptions in a special way. For example in mips there's no stepping feature by hardware, so radare has an own implementation using a mix of code analysis and software breakpoints to bypass this limitation.

To get the basic help of the debugger you can just type '!help':

[0x4A13B8C0]> !help
 Information
  info               show debugger and process status
  msg                show last debugger status message
  pid [tid] [action] show pid of the debug process, current tid and childs, or set tid.
  status             show the contents of /proc/pid/status
  signal             show signals handler
  maps[*]            flags the current memory maps (.!rsc maps)
  syms               flags all syms of the debugged program (TODO: get syms from libs too)
  fd[?][-#] [arg]    file descriptors (fd? for help)
  th[?]              threads control command
 Stack analysis
  bt                 backtrace stack frames (use :!bt for user code only)
  st                 analyze stack trace (experimental)
 Memory allocation
  alloc [N]          allocates N bytes (no args = list regions)
  mmap [F] [off]     mmaps a file into a memory region
  free               free allocated memory regions
  imap               map input stream to a memory region (DEPRECATED)
 Loader
  run [args]         load and start execution
  (un)load           load or unload a program to debug
  kill [-S] [pid]    sends a signal to a process
  {a,de}ttach [pid]  attach or detach target pid
 Flow Control
  jmp [addr]         set program counter
  call [addr]        enters a subroutine
  ret                emulates a return from subroutine
  skip [N]           skip (N=1) instruction(s)
  step{o,u,bp,ret}   step, step over, step until user code, step until ret
  cont{u,uh,sc,fork} continue until user code, here, syscall or fork
 Tracing
  trace [N]          trace until bp or eof at N debug level
  tt [size]          touch trace using a swapable bps area
  wtrace             watchpoint trace (see !wp command)
  wp[m|?] [expr]     put a watchpoint (!wp? for help) (wpm for monitor)
 Breakpoints
  bp [addr]          put a breakpoint at addr (no arg = list)
  mp [rwx] [a] [s]   change memory protections at [a]ddress with [s]ize
  ie [-][event]      ignore debug events
 Registers
  [o|d|fp]regs[*]    show registers (o=old, d=diff, fp=fpu, *=radare)
  reg[s|*] [reg[=v]  show get and set registers
  oregs[*]           show old registers information (* for radare)
  dr[rwx-]           DR registers control (dr? for help) (x86 only)
 Other
  dump/restore [N]   dump/restore pages (and registers) to/from disk
  dall               dump from current seek to cfg.limit all available bytes (no !maps required)
  core               dump core of the process
  hack [N]           Make a hack.
  inject [bin]       inject code inside child process (UNSTABLE)
Usage: !<cmd>[?] <args> @ <offset>     ; see eval dbg. fmi