-
-
Save pnomolos/03b803ac9b566ffe2c40 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Attaching to the process with GDB | |
Populate your .gdbinit and .gdb directories | |
In ~/.gdbinit: | |
define session-ruby | |
source ~/.gdb/ruby | |
end | |
Next, you need to download http://eigenclass.org/hiki.rb?c=plugin;plugin=attach_download;p=ruby+live+process+introspection;file_name=ruby | |
And place it in ~/.gdb/ruby. | |
$ mkdir -p ~/.gdb | |
$ wget 'http://eigenclass.org/hiki.rb?c=plugin;plugin=attach_download;p=ruby+live+process+introspection;file_name=ruby' | |
$ mv ruby ~/.gdb | |
Attach to the process, load the ruby helpers, and redirect stdout: | |
$ ps ax | grep ruby | |
845 s000 S+ 0:00.91 /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby /usr/bin/chef-indexer -l debug | |
932 s001 R+ 0:00.00 grep ruby | |
842 s002 S+ 0:00.44 /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby /usr/bin/stompserver | |
The important part here is the very first segment of the line (the PID). | |
$ gdb /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/bin/ruby 845 | |
The first argument to gdb should be the full path to the ruby executable that is running the process. | |
Start your debug session | |
From above, you should see a bunch of output like this: | |
... | |
Loaded symbols for /srv/ruby/1.8.6/lib/ruby/1.8/i686-linux/nkf.so | |
0xbfffe402 in +kernel_vsyscall () | |
And then you'll wind up at... | |
(gdb) | |
First things first, load up the ruby helpers. | |
(gdb) session-ruby | |
Then, redirect stdout to a file, so we can capture the output for later. | |
(gdb) redirect_stdout | |
Open up a second terminal, and you can watch the output from your debug session: | |
$ tail -f /tmp/ruby-debug.PID | |
Where PID above is equal to the PID you attached to with gdb. | |
Now that you are watching, flip back to your gdb session and.. | |
Get some data | |
(gdb) eval "caller" | |
(gdb) rb_object_counts | |
(gdb) eval "total = ObjectSpace.each_object {|x| if x.class.to_s =~ /Puppet/; puts '---'; puts x.inspect; end }; puts \"---\nTotal Objects: #{total}\"" | |
Or, for arrays only: | |
(gdb) eval "total = ObjectSpace.each_object(Array){|x| puts '---'; puts x.inspect }; puts \"---\nTotal Arrays: #{total}\"" | |
You should see a stack trace, a long count of the number of objects in the system. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# taken from http://eigenclass.org/hiki.rb?ruby+live+process+introspection | |
################### | |
# #### RUBY STUFF | |
define eval | |
call(rb_p(rb_eval_string_protect($arg0,(int*)0))) | |
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 | |
define restore_stdout | |
call rb_eval_string("$stdout = $_old_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 | |
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 | |
define rb_locals | |
eval "local_variables.map{|x| puts '%s = %s' % [x, eval(x)]}; nil" | |
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 | |
document rp | |
ruby¤ÎÁȤ߹þ¤ß¥ª¥Ö¥¸¥§¥¯¥È¤òɽ¼¨¤¹¤ë | |
end | |
define nd_type | |
print nodetype($arg0) | |
end | |
document nd_type | |
ruby node ¤Î·¿¤òɽ¼¨ | |
end | |
define nd_file | |
print ((NODE*)$arg0)->nd_file | |
end | |
document nd_file | |
node ¤Î¥½¡¼¥¹¥Õ¥¡¥¤¥ë̾¤òɽ¼¨ | |
end | |
define nd_line | |
print nodeline($arg0) | |
end | |
document nd_line | |
node ¤Î¹ÔÈÖ¹æ¤òɽ¼¨ | |
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment