Rubykaigi 2010 present part3
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”).