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))