## Debugging: debugger, GDB, valgrind

With Rubinius, there are two distinct things that may need debugging
(sometimes at the same time.) There is the Ruby code, for which 'debugger'
exists. debugger is a full-speed debugger, which means that there is no extra
compilation or flags to enable it but at the same time, code normally does not
suffer a performance penalty from the infrastructure.  This is achieved using
a combination of bytecode substitution and Rubinius' Channel IO interface.
Multithreaded debugging is supported (credit for the debugger goes to Adam
Gardiner.)

On the C side, the trusty workhorse is the Gnu Debugger or GDB. In addition
there is support built in for Valgrind, a memory
checker/lint/debugger/analyzer hybrid.


### debugger

The nonchalantly named debugger is specifically the debugger for Ruby code,
although it does also allow examining the VM as it runs. The easiest way to
start it is to insert either a +breakpoint+ or +debugger+ method call anywhere
in your source code. Upon running this method, the debugger starts up and
awaits your command at the instruction where the +breakpoint+ or +debugger+
method used to be. For a full explanation of the debugger, refer to [currently
the source but hopefully docs shortly.] You will see this prompt and there is
a trusty command you can try to get started:

  rbx:debug> help


### GDB

To really be able to use GDB, make sure that you build Rubinius with DEV=1
set.  This disables optimisations and adds debugging symbols.

There are two ways to access GDB for Rubinius. You can simply run
shotgun/rubinius with gdb (use the builtin support so you do not need to worry
about linking etc.):

*   Run `shotgun/rubinius --gdb`, place a breakpoint (break main, for example)
    and then r(un.)
*   Alternatively, you can run and then hit ^C to interrupt.

You can also drop into GDB from Ruby code with +Kernel#yield_gdb+ which uses a
rather rude but very effective method of stopping execution to start up GDB.
To continue past the +yield_gdb+, j(ump) to one line after the line that you
have stopped on.

Useful gdb commands and functions (remember, using the p(rint) command in GDB
you can access pretty much any C function in Rubinius. Also see ./.gdbinit):

*   rbt

    Prints the backtrace of the Ruby side of things. Use this in conjunction
    with gdb's own bt which shows the C backtrace.

*   rp some_obj

    Prints detailed information about a given Ruby object.

*   rps some_obj

    Prints brief information about a given Ruby object.

The gdb rp and rps commands use the C-exported functions __show__ and
__show_simple__. The default output of these functions is defined on the
TypeInfo class. The other C++ classes define the show and show_simple
functions to override the default output. The default output is to show the
class name and the address of the instance like "#<SomeClass:0x3490301".

The immediate classes like NilClass, TrueClass, etc. and the numeric classes
like Fixnum and Bignum define show and show_simple to both output their
values. More complex classes like CompiledMethod and Tuple use the show_simple
function to limit the information printed.

See also vm/type_info.hpp


### Valgrind

Valgrind is a program for debugging, profiling and memory-checking programs.
The invocation is just  `shotgun/rubinius --valgrind`.  See
http://valgrind.org for usage information.


### Probes

The C++ VM uses the TaskProbe class to define and manage several probes that,
when enabled, print information about VM operations.  The probes can be
enabled from an environmental variable or from Ruby code. To enable all probes
from the environment, use:

    PROBE=all vm/vm  OR
    PROBE=1 vm/vm

To enable only certain probes from the environment, use e.g.:

    PROBE=start_method,execute_instruction vm/vm

From Ruby code, enable or disable probes globally with the TaskProbe class
method. For example:

    TaskProbe.enable :execute_instruction
    TaskProbe.disable :start_method

Or, create a TaskProbe instance and use the #show method with a block:

    meth = TaskProbe.new :start_method
    meth.show { # some ruby code here }

See also kernel/common/taskprobe.rb and vm/builtin/taskprobe.hpp.
