10.3 Macros

The radare shell support macro definitions and these ones can be used to make up your own set of commands into a macro and then use it from the shell by just giving the name and arguments. You can understand a macro as a function.

Let's see how to define a macro:

[0x465D8810]> (?
Usage: (foo\n..cmds..\n)
 Record macros grouping commands
 (foo args\n ..)  ; define a macro
 (-foo)            ; remove a macro
 .(foo)            ; to call it
Argument support:
 (foo x y\n$1 @ $2)     ; define fun with args
 .(foo 128 0x804800) ; call it with args

The command to manage macros is '('. The first thing we can do is a hello world:

[0x465D8810]> (hello
.. ?e Hello World
.. ?e ===========
.. )
[0x465D8810]> .(hello)
Hello World
===========
[0x465D8810]> 

Macros supports arguments, and they are referenced with $# expressions.

Here's an example of how to define a simple oneliner function called 'foo' accepting two arguments to be used to print 8bit values from an address.

; Create our macro
[0x465D8810]> (dump addr len
.. p8 $1 @ $0)

; List defined macros
[0x465D8810]> (
0 dump: p8 $1 @ $0

; Call the macro
[0x465D8810]> .(dump esp 10)
01 00 00 00 e4 17 e6 bf 00 00

; Remove it!
[0x465D8810]> (-dump)

We can define these macros in our ~/.radarerc

$ cat ~/.radarerc
(dump addr len
  p8 $1 @ $0)

It is also possible to recursively call a macro to emulate a loop. Here's a simple example of a recursive loop using macros in radare:

(loop times cmd
  ? $0 == 0
  ?? ()
  $1
  .(loop $0-1 $1))