This page is a collection of tricks I use to debug shotgun. It is not a complete reference so don't forget your ninja skills !

~~~~ zimbatm

Introduction

For good shotgun hackery, don't forget to compile the interpreter with DEV=1.

rake build:vm:clean build:vm:dev

GDB debugging

You can run most commands with the --gdb flag so that you get the symbols loaded automatically.

  • shotgun/rubinius
  • bin/mspec
  • bin/ci

...

bin/mspec --gdb spec/ruby/1.8/language/constants_spec.rb
  1. Set the breakpoints.
  2. Type "run" to execute your code

Alternatively, you can use the kernel method #yield_gdb() to generate a SIGSEGV that activates GDB when that line is hit. The object passed to yield_gdb is then available for inspection as t1, e.g. p _inspect(t1). Note that if you use yield_gdb, it generates a SIGSEGV, so it is necessary to jump past the line containing the yield_gdb command in order to resume your program. You will probably be unable to jump to where you intend unless you build shotgun in dev mode.

Useful GDB Commands

Some useful commands (once gdb is stopped):

  • break shotgun_method # set a breakpoint at the start of the specified shotgun method
  • rbt # print ruby's backtrace
  • p _inspect(some_var) # shows ruby OBJECT
  • j some_line # Jump to the specified line

Print the sexp

./shotgun/rubinius
irb(main):001:0> 'puts "Hello World"'.to_sexp
=> [:newline, 1, "(eval)", [:fcall, :puts, [:array, [:str, "Hello World"]]]]

Print the bytecode

./shotgun/rubinius
irb(main):001:0> puts Compiler.compile_file("your_test_file.rb").decode
0000:  push_literal               "Hello world"
0002:  string_dup                 
0003:  push_self                  
0004:  set_call_flags             1
0006:  send_stack                 :puts, 1
0009:  pop                        
0010:  push_true                  
0011:  sret                       
=> nil

To get kernel bytecode, add the appropriate flags :

puts Compiler.compile_file("your_test_file.rb", ["rbx-kernel", "rbx-safe-math"]).decode

...field of non-reference bugs

The easiest way, is to break on "machine_handle_fire". Type "break machine_handle_fire" in gdb, then run your breaking code. When gdb stops, you should get something like this :

(gdb) bt
#0  machine_handle_fire (kind=2) at machine.c:267
#1  0xb7e1db23 in cpu_const_set (state=0x804b7e8, c=0x806be98, sym=0x809b, 
    val=0xd, under=0xd) at ../../shotgun/lib/state.h:321
#2  0xb7e2562f in cpu_run (state=0x804b7e8, c=0x806be98, setup=0)
    at ../../shotgun/lib/instruction_dt.gen:184
#3  0xb7e595d5 in machine_run (m=0x804b5b8) at machine.c:323
#4  0xb7e596e7 in machine_run_file (m=0x804b5b8, 
    path=0xbff54e24 "/home/zimbatm/src/rubinius/const_set/runtime/loader.rbc")
    at machine.c:348
#5  0xb7e3ff2f in environment_load_machine (e=0x804b008, m=0x804b5b8)
    at environment.c:176
#6  0x08048a73 in main (argc=2, argv=0xbff53bc4) at main.c:98

as you can see, the culprit is really near, you just need to go on "up" in the stack.

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

0.1069% complete

 

Completed 9 of 13 tickets