Debugger Aliases and Macros

rocky edited this page Feb 10, 2013 · 3 revisions

The simplest form of macro, an “alias” is a debugger command. You can use it to define a short command name to an existing command.

The debugger comes with a number of pre-defined aliases; for example “s” for step and “c” for continue. If you want, you can remove them with unalias; or you can redefine them to mean other things via alias.

But beware: there are some hard-coded hacked suffixes that are used in certain commands. In particular, the stepping commands use suffixes ‘+’, ‘-’, ‘>’, ‘<’, and ‘!’ to override granularity on stepping. Other commands which normally require confirmation like `quit` or `kill` can be silenced using the suffix ‘!’.

gdb has a more more complicated and general macro command for making new debugger commands. But Ruby is already a nice programming language, so why invent another? Instead in trepan we let you create your own expansion command in Ruby. The expansion occurs via a Proc which you create.

Suppose you wanted to make “l=” expands to the debugger command `list .`. An alias can’t be used here because we want one token `l=` to expand to two tokens `list` and `.`. But writing a macro for this is easy:

macro l= proc{'list .'}

Sometimes though you’ll want to run more than a single command. For that, instead of returning a string, you should return a list of strings.

The below creates a macro called finish+ which issues two debugger commands finish followed by step:

macro fin+ proc{|*args| %w(finish step)}

Macros should return either a String or an Array of Strings. This first string is used as the next command. If there are more strings, those get pushed on a command queue.

Strings are tokenized by a simple String#split .

Macro processing is done right after splitting on “;;” so if the macro returns a string containing “;;” this will not be handled on the string returned. However subsequent strings pushed on the queue will be inspected for “;;”.

Macros are also be passed arguments from the command line.
Here is another example using arguments. I use the following to debug a debugger command:

macro dbgcmd proc{|*args| ["set debug dbgr", "debug $trepan_cmdproc.commands['\#{args[0]}'].run(\#{args.inspect})"]}

With the above, ‘dbgcmd list 5’ will ultimately expand to:

set debug dbgr
debug $trepan_cmdproc.commands['list'].run(['list', '5'])

and will debug the debugger’s list command on as though command
list 5 were entered.