Skip to content

Rubykaigi 2010 present part3

rocky edited this page Sep 1, 2010 · 3 revisions

I want folks to think about this debugger in the same way that people think about gdb for C. It is both a high-level debugger for C++ or C and a low-level debugger as well. It can debug optimized C code and assembly code. In Ruby, I’d like folks who work on the VM or develop VM optimizations to be able to use this debugger as a tool just someone might use gdb. But there is still something for novices and intermediate users.

So let me show some of the low-level access available.

Let’s restart:

 (rbdbgr): restart

Previously, I stepped by event type. But I can also step until a particular expression evaluates to “true”. Let us use that to get intto that eval string again:

(rbdbgr): step until 2 == a

Now I can see exactly where I am in the program by looking at the value of the VM PC:

 (rbdbgr): info reg pc 

A dissassembly shows the PC offset as well:

(rbdbgr): disassemble
== disasm: <RubyVM::InstructionSequence:<top /src/git/papers/rubykaigi-2010/code/eval.rb>@(eval)>
local table (size: 3, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 3] a          [ 2] b          
     0000 trace            1                                               (   1)
     0002 putobject        2
     0004 setdynamic       a, 0
     0007 trace            1                                               (   2)
 --> 0009 putobject        3
     0011 dup              
     0012 setdynamic       b, 0
     0015 leave            
(rbdbgr): 

I can set breakpoints not only at line numbers but I can also set them at VM offsets as well:

 (rbdbgr): break O15
(rbdbgr): disassemble
== disasm: <RubyVM::InstructionSequence:<top /src/git/papers/rubykaigi-2010/code/eval.rb>@(eval)>
local table (size: 3, argc: 0 [opts: 0, rest: -1, post: 0, block: -1] s1)
[ 3] a          [ 2] b          
     0000 trace            1                                               (   1)
     0002 putobject        2
     0004 setdynamic       a, 0
     0007 trace            1                                               (   2)
 --> 0009 putobject        3
     0011 dup              
     0012 setdynamic       b, 0
B    0015 leave            
(rbdbgr): 

Disassembly shows the breakpoint location.

And finally, I can step by VM instruction. By default it is turned off. But I can set the filter-event mask to allow that.

(rbdbgr): show events
(rbdbgr): set events brkpt, c_call, c_return, call, class, end, line, raise, return, insn

Normally we don’t stop if the next event is at the same line. But you can override that behavior with:

(rbdbgr): step-

Notice I now have ‘..’ which means I am at a VM instruction which is not a line boundary.

(rbdbgr): disassemble

I can see the current SP stack with

  (rbdbgr): info reg sp  
(rbdbgr): info reg sp
  1: #<RubyVM::Env:0x9139a30>
  2: nil

If I do another step-, 3 is pushed onto the stack

(rbdbgr): step-   
(rbdbgr): info reg sp
 1: 3
 2:  #<RubyVM::Env:0x9139a30>
 3: nil

And another step- over the dup, and you see that dup duplicates the top stack item.

  (rbdbgr): step -
  (rbdbgr): info reg sp
rbdbgr): info reg sp
  1: 3
  2: 3
  3: #<RubyVM::Env:0x9139a30>
  4: nil

If I continue I should hit the breakpoint I set.

(rbdbgr): continue

Note the xx icon which means breakpoint.

Breakpoints are VM assisted. So is “step over” (or “next”) and “step out” (or “finish”).