# Copy this file into you home directory as '.gdbinit'. # # GDB will then load these macros automatically. ################################################################### # Jamis Buck's Tricks ################################################################### define rb_bt set $ary = (int)backtrace(-1) set $count = *($ary+8) set $index = 0 while $index < $count x/1s *((int)rb_ary_entry($ary, $index)+12) set $index = $index + 1 end end document rb_bt Print the ruby stack trace interpreting backtrace as a Ruby array of string. end define rb_raise call rb_raise((int)rb_eException, "Forced exception from GDB to get a valid ruby stack trace") end document rb_raise Raise a Ruby exception from gdb. end ################################################################### # Mauricio Fernandez's Ruby macros (Eigenclass.org) ################################################################### define eval call(rb_p(rb_eval_string_protect($arg0,(int*)0))) end document eval Evaluate an arbitrary Ruby expression from current gdb context. end define redirect_stdout call rb_eval_string("$_old_stdout, $stdout = $stdout, File.open('/tmp/ruby-debug.' + Process.pid.to_s, 'a'); $stdout.sync = true") end document redirect_stdout Hijack Ruby $stdout and redirect it to /tmp/ruby-debug-. Useful to redirect ruby macro output to a separate file. end define restore_stdout call rb_eval_string("$stdout = $_old_stdout") end document restore_stdout Restore Ruby $stdout to its original value after hijacking it with redirect_stdout. end define rb_finish call rb_eval_string_protect("set_trace_func lambda{|event, file, line, id, binding, classname| if /return/ =~ event; sleep 0; set_trace_func(nil) end}",(int*)0) tbreak rb_f_sleep cont end document rb_finish Execute the current Ruby method until it returns and interrupts the process at a safe point (the rb_f_sleep function). You should always call this macro before evaling Ruby code in gdb. end define rb_object_counts call rb_eval_string_protect("counts = Hash.new{|h,k| h[k] = 0}; ObjectSpace.each_object{|o| counts[o.class] += 1}; counts.sort_by{|k,c| c}.reverse.each{|k,c| puts '%7d %s' % [c, k] } ",(int*)0) end document rb_object_counts Count and print all living objects by type. end define rb_locals eval "local_variables.map{|x| puts '%s = %s' % [x, eval(x)]}; nil" end document rb_locals Print local variables and their values. end define rp if ($arg0 & 0x1) echo T_FIXNUM\n print (long)$arg0 >> 1 else if ($arg0 == 0) echo T_FALSE\n else if ($arg0 == 2) echo T_TRUE\n else if ($arg0 == 4) echo T_NIL\n else if ($arg0 == 6) echo T_UNDEF\n else if (($arg0 & 0xff) == 0x0e) echo T_SYMBOL\n output $arg0 >> 8 echo \n call rb_id2name($arg0 >> 8) else set $rbasic = (struct RBasic*)$arg0 # output $rbasic # echo \ =\ # output *$rbasic # echo \n set $flags = (*$rbasic).flags & 0x3f if ($flags == 0x01) echo T_NIL\n echo impossible\n else if ($flags == 0x02) echo T_OBJECT\n print *(struct RObject*)$rbasic else if ($flags == 0x03) echo T_CLASS\n # rb_classname($arg0) else if ($flags == 0x04) echo T_ICLASS\n print *(struct RClass*)$rbasic else if ($flags == 0x05) echo T_MODULE\n print *(struct RClass*)$rbasic else if ($flags == 0x06) echo T_FLOAT\n print *(struct RFloat*)$rbasic else if ($flags == 0x07) echo T_STRING\n print *(struct RString*)$rbasic else if ($flags == 0x08) echo T_REGEXP\n print *(struct RRegexp*)$rbasic else if ($flags == 0x09) echo T_ARRAY\n print *(struct RArray*)$rbasic else if ($flags == 0x0a) echo T_FIXNUM\n echo impossible\n else if ($flags == 0x0b) echo T_HASH\n print *(struct RHash*)$rbasic else if ($flags == 0x0c) echo T_STRUCT\n print *(struct RStruct*)$rbasic else if ($flags == 0x0d) echo T_BIGNUM\n print *(struct RBignum*)$rbasic else if ($flags == 0x0e) echo T_FILE\n print *(struct RFile*)$rbasic else if ($flags == 0x20) echo T_TRUE\n echo impossible\n else if ($flags == 0x21) echo T_FALSE\n echo impossible\n else if ($flags == 0x22) echo T_DATA\n print *(struct RData*)$rbasic else if ($flags == 0x23) echo T_MATCH\n print *(struct RMatch*)$rbasic else if ($flags == 0x24) echo T_SYMBOL\n echo impossible\n else if ($flags == 0x3c) echo T_UNDEF\n echo impossible\n else if ($flags == 0x3d) echo T_VARMAP\n else if ($flags == 0x3e) echo T_SCOPE\n else if ($flags == 0x3f) echo T_NODE\n print (NODE*)$arg0 else echo Unknown\n end end end end end end end end end end end end end end end end end end end end end end end end end end end end end end define nd_type print nodetype($arg0) end define nd_file print ((NODE*)$arg0)->nd_file end define nd_line print nodeline($arg0) end # ruby node のメンバを表示 define nd_head print "u1.node" what $arg0.u1.node p $arg0.u1.node end define nd_alen print "u2.argc" what $arg0.u2.argc p $arg0.u2.argc end define nd_next print "u3.node" what $arg0.u3.node p $arg0.u3.node end define nd_cond print "u1.node" what $arg0.u1.node p $arg0.u1.node end define nd_body print "u2.node" what $arg0.u2.node p $arg0.u2.node end define nd_else print "u3.node" what $arg0.u3.node p $arg0.u3.node end define nd_orig print "u3.value" what $arg0.u3.value p $arg0.u3.value end define nd_resq print "u2.node" what $arg0.u2.node p $arg0.u2.node end define nd_ensr print "u3.node" what $arg0.u3.node p $arg0.u3.node end define nd_1st print "u1.node" what $arg0.u1.node p $arg0.u1.node end define nd_2nd print "u2.node" what $arg0.u2.node p $arg0.u2.node end define nd_stts print "u1.node" what $arg0.u1.node p $arg0.u1.node end define nd_entry print "u3.entry" what $arg0.u3.entry p $arg0.u3.entry end define nd_vid print "u1.id" what $arg0.u1.id p $arg0.u1.id end define nd_cflag print "u2.id" what $arg0.u2.id p $arg0.u2.id end define nd_cval print "u3.value" what $arg0.u3.value p $arg0.u3.value end define nd_cnt print "u3.cnt" what $arg0.u3.cnt p $arg0.u3.cnt end define nd_tbl print "u1.tbl" what $arg0.u1.tbl p $arg0.u1.tbl end define nd_var print "u1.node" what $arg0.u1.node p $arg0.u1.node end define nd_ibdy print "u2.node" what $arg0.u2.node p $arg0.u2.node end define nd_iter print "u3.node" what $arg0.u3.node p $arg0.u3.node end define nd_value print "u2.node" what $arg0.u2.node p $arg0.u2.node end define nd_aid print "u3.id" what $arg0.u3.id p $arg0.u3.id end define nd_lit print "u1.value" what $arg0.u1.value p $arg0.u1.value end define nd_frml print "u1.node" what $arg0.u1.node p $arg0.u1.node end define nd_rest print "u2.argc" what $arg0.u2.argc p $arg0.u2.argc end define nd_opt print "u1.node" what $arg0.u1.node p $arg0.u1.node end define nd_recv print "u1.node" what $arg0.u1.node p $arg0.u1.node end define nd_mid print "u2.id" what $arg0.u2.id p $arg0.u2.id end define nd_args print "u3.node" what $arg0.u3.node p $arg0.u3.node end define nd_noex print "u1.id" what $arg0.u1.id p $arg0.u1.id end define nd_defn print "u3.node" what $arg0.u3.node p $arg0.u3.node end define nd_old print "u1.id" what $arg0.u1.id p $arg0.u1.id end define nd_new print "u2.id" what $arg0.u2.id p $arg0.u2.id end define nd_cfnc print "u1.cfunc" what $arg0.u1.cfunc p $arg0.u1.cfunc end define nd_argc print "u2.argc" what $arg0.u2.argc p $arg0.u2.argc end define nd_cname print "u1.id" what $arg0.u1.id p $arg0.u1.id end define nd_super print "u3.node" what $arg0.u3.node p $arg0.u3.node end define nd_modl print "u1.id" what $arg0.u1.id p $arg0.u1.id end define nd_clss print "u1.value" what $arg0.u1.value p $arg0.u1.value end define nd_beg print "u1.node" what $arg0.u1.node p $arg0.u1.node end define nd_end print "u2.node" what $arg0.u2.node p $arg0.u2.node end define nd_state print "u3.state" what $arg0.u3.state p $arg0.u3.state end define nd_rval print "u2.value" what $arg0.u2.value p $arg0.u2.value end define nd_nth print "u2.argc" what $arg0.u2.argc p $arg0.u2.argc end define nd_tag print "u1.id" what $arg0.u1.id p $arg0.u1.id end define nd_tval print "u2.value" what $arg0.u2.value p $arg0.u2.value end define rb_p call rb_p($arg0) end define rb_id2name call rb_id2name($arg0) end define rb_classname call classname($arg0) rb_p $ p *(struct RClass*)$arg0 end define rb_backtrace call rb_backtrace() end echo **** Loaded Ruby Macros Successfully ****\n