Hacking Ruby    with   Python     @tyamadajp
光ある所、影がありコードある所、闇がある
闇の名は、バグ。そしてバグを殺す者、
Ruby Debugger~僕と契約して闇デバッガになろうよ!~
みなさんオススメのデバッガは?0. p+?            (?!)1. debug.rb?      (旧型)2. ruby-debug? (普通)3. rb-trepanning? (新型)4. others?#ベースの機能を生かした...
デバッガのいい所・どこまでも覗ける・動いている状態を覗ける・あろうことか、手まで出せる「言語仕様?そんなの関係ねぇ!」「もし闇の住人がデバッガーの       解説ページを読んだら」
さて今宵のデバッガは・・・
さて今宵のデバッガは・・・  GDB
さて今宵のデバッガは・・・   The   GNU   Debugger
さて今宵のデバッガは・・・… の Python 拡張
さて今宵のデバッガは・・・ GDB/Python       明日の Ruby のために、       今夜は Python
なにそれこわい
こわくないよ!> GDB/Python1. GDB を 100% API control → ブレークポイントの操作とか2. GDB そのものも拡張 →新コマンド追加 / (gdb)... →簡易関数の追加 / $func(...) → pri...
こんな感じ(実装例)(gdb) p self$299 = (struct RTypedData *) 0x64b2c0,   type=iseq ($300), data=0x731ee0 ($301)(gdb) pp self$302 = (...
それ $RUBY/.gdbinit でできるよ?ええ、あるのですが・・・・主力は内蔵 eval や dump 関数?・なので展開能力が控えめ ( ぬるぽ避け? )  (gdb) rp recv  T_CLASS: $1156 = (struct...
ぬるぽを恐れず何でも展開(gdb) pp recv$1158 = (struct RClass *) 0x655310 [Time]dump: {basic = {flags = 2, klass = 6640360}, ptr=0x6e4e2...
GDB script ではダメですか?・ まともな制御構文がない → if else if else if else end end end・ スコープ概念が(ほとんど)ない・ 遅い。当人比で最大 100+ 倍以上・ 限りなく貧弱なデータ操作機...
GDB Python API - basicimport gdb# vmは gdb.Value オブジェクトだが rb_vm_t* の型を保持vm = gdb.parse_and_eval(“ruby_current_vm”)# これも gdb...
GDB Command – extending gdbimport gdbclass HelloCommand(gdb.Command):   """Sample GDB command in Python"""   def __init__(...
GDB Command – easy wayimport gdb@gdbcommand(“hello-cmd“)def hello(*args):   """   Sample GDB command in Python   Usage: he...
GDB Command – easy way, impldef gdbcommand(*args):   """Turns decorated function into GDB command"""   opts = [args[0], gd...
GDB Pretty Printerclass HelloPrinter(object):   """Print (hello_t *) type"""   def __init__(self, val): self.val = val   #...
おまけ: Ruby と Python の狂演$ rlwrap gdb -q -readnow --args ./ruby1.9.1 tarai.rb(gdb) b vm_exec(gdb) run(gdb) python sys.argv = ...
おまけ: gdb.rb – GDB/Ruby in Py*https://github.com/tmm1/gdb.rb 「 gdb hooks for MRI/REE (and some for YARV) 」(gdb) b vm_exec i...
まとめ1. Ruby のデバッグ・学習に使ってみた2. GDB/Python は強力なツール3.正直わけがわからないよ!「明日の Ruby のために、今夜は Python 」参考文献:・ sourceware.org/gdb/onlinedoc...
Upcoming SlideShare
Loading in …5
×

Hacking Ruby with Python

2,360 views
2,242 views

Published on

Short introduction of GDB/Python, with actual examples for debugging and (sort of) running Ruby-as-a-debugger-of-oneself on top of it.

This was prepared for YamiRubyKaigi 2011 (Darkness of RubyKaigi2011), but unfortunately gave up doing actual presentation due to too many pages.

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
2,360
On SlideShare
0
From Embeds
0
Number of Embeds
8
Actions
Shares
0
Downloads
26
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Hacking Ruby with Python

  1. 1. Hacking Ruby with Python @tyamadajp
  2. 2. 光ある所、影がありコードある所、闇がある
  3. 3. 闇の名は、バグ。そしてバグを殺す者、
  4. 4. Ruby Debugger~僕と契約して闇デバッガになろうよ!~
  5. 5. みなさんオススメのデバッガは?0. p+? (?!)1. debug.rb? (旧型)2. ruby-debug? (普通)3. rb-trepanning? (新型)4. others?#ベースの機能を生かした# JRuby, Rubinius 用のとかも#ありますよね
  6. 6. デバッガのいい所・どこまでも覗ける・動いている状態を覗ける・あろうことか、手まで出せる「言語仕様?そんなの関係ねぇ!」「もし闇の住人がデバッガーの       解説ページを読んだら」
  7. 7. さて今宵のデバッガは・・・
  8. 8. さて今宵のデバッガは・・・ GDB
  9. 9. さて今宵のデバッガは・・・ The GNU Debugger
  10. 10. さて今宵のデバッガは・・・… の Python 拡張
  11. 11. さて今宵のデバッガは・・・ GDB/Python 明日の Ruby のために、 今夜は Python
  12. 12. なにそれこわい
  13. 13. こわくないよ!> GDB/Python1. GDB を 100% API control → ブレークポイントの操作とか2. GDB そのものも拡張 →新コマンド追加 / (gdb)... →簡易関数の追加 / $func(...) → print ハイジャック / pretty printer
  14. 14. こんな感じ(実装例)(gdb) p self$299 = (struct RTypedData *) 0x64b2c0, type=iseq ($300), data=0x731ee0 ($301)(gdb) pp self$302 = (struct RTypedData *) 0x64b2c0, type=iseq ($303), data=0x731ee0 ($304)$305 = (const rb_data_type_t *) 0x7ffff7dbe780$306 = (rb_iseq_t *) 0x731ee0, <compiled>:3, type=ISEQ_TYPE_TOP ・・・まあ色々デコードしてくれます
  15. 15. それ $RUBY/.gdbinit でできるよ?ええ、あるのですが・・・・主力は内蔵 eval や dump 関数?・なので展開能力が控えめ ( ぬるぽ避け? )  (gdb) rp recv  T_CLASS: $1156 = (struct RClass *) 0x655310      →ソース読解の道具が欲しかった      →自分でデコードするのがよい練習
  16. 16. ぬるぽを恐れず何でも展開(gdb) pp recv$1158 = (struct RClass *) 0x655310 [Time]dump: {basic = {flags = 2, klass = 6640360}, ptr=0x6e4e20, m_tbl=0x6e4e40, iv_index_tbl=0x0}m_tbl: +, -, <=>, _dump, asctime, ctime, …(gdb) pp ruby_current_thread->cfp->iseq 2$1072 = (rb_iseq_t *) 0x75c9c0, MAIN, /home/tai/tarai.rb:1(p=0x70a260/$1073, l=0x70a260/$1074)line#0003: VALUE ラップもの、 ID 、 $1075 putstring NODE 、 rb_iseq_t 、 rb_vm_t... 自動で型判定し p or pp で $1076 getclassvariable … 中身を徹底表示
  17. 17. GDB script ではダメですか?・ まともな制御構文がない → if else if else if else end end end・ スコープ概念が(ほとんど)ない・ 遅い。当人比で最大 100+ 倍以上・ 限りなく貧弱なデータ操作機能とライブラリ     「 GDB script がやられたか・・・」     「所詮あやつは言語以前の存在」
  18. 18. GDB Python API - basicimport gdb# vmは gdb.Value オブジェクトだが rb_vm_t* の型を保持vm = gdb.parse_and_eval(“ruby_current_vm”)# これも gdb.Value オブジェクトだが、 rb_thread_t* の型を維持th = vm[running_thread]# いわゆる構造体ダンプ :(gdb) p *ruby_current_vmprint(vm.dereference())# ポインタ演算したいときには char* にしたりpointer_op(th.cast(gdb.lookup_type(“char”).pointer()))# CLI 側で参照できるよう $ や $N に戻したりもできるgdb.execute(“p (%s)%ld” % (th.type, long(th)))gdb.execute(“set $foo = %ld” % long(th))
  19. 19. GDB Command – extending gdbimport gdbclass HelloCommand(gdb.Command): """Sample GDB command in Python""" def __init__(self): super(self.__class__, self).__init__( "hello-cmd", gdb.COMMAND_OBSCURE) def invoke(self, arg, from_tty): args = gdb.string_to_argv(arg) print("arg is [%s]" % ", ".join(args))HelloCommand() 拡張1つにクラスを1つ※ ロードは (gdb) python execfile(“hello.py”) などで
  20. 20. GDB Command – easy wayimport gdb@gdbcommand(“hello-cmd“)def hello(*args): """ Sample GDB command in Python Usage: hello-cmd args """ print("arg is [%s]" % ", ".join(args)) バイト数 50% カット!
  21. 21. GDB Command – easy way, impldef gdbcommand(*args): """Turns decorated function into GDB command""" opts = [args[0], gdb.COMMAND_OBSCURE] #FIXME def wrap(func): name = opts[0] or func.func_name def init(self): super(self.__class__, self).__init__(name, *opts[1:]) def invoke(self, arg, from_tty): func(*gdb.string_to_argv(arg)) type("", (gdb.Command,), { __doc__: func.__doc__, __init__: init, invoke: invoke, })() return func return wrap デコレータ、 Ruby にも 本気で欲しくなったり ※ スライドに収めるため機能とコードをカットしています。バグってたらごめんなさい
  22. 22. GDB Pretty Printerclass HelloPrinter(object): """Print (hello_t *) type""" def __init__(self, val): self.val = val # 表示する文字列又は gdb.Value を返す。後者の場合は # 再度 pretty-printing 処理が試みられる。以下はダミー。 def to_string(self): return "hogehoge" # 表示ヒント。 "array", "map", "string" のいずれかを返す def display_hint(self): return "string"# カスタムプリンタが反応できるようチェッカを登録def ckval(gv): if gv.type == gdb.lookup_type("hello_t").pointer(): return HelloPrinter(gv) return None print 以外にも、あらゆるgdb.pretty_printers.append(ckval) 表示処理に適用される
  23. 23. おまけ: Ruby と Python の狂演$ rlwrap gdb -q -readnow --args ./ruby1.9.1 tarai.rb(gdb) b vm_exec(gdb) run(gdb) python sys.argv = [“gdb”] # GDB 側の漏れ対応(gdb) python execfile("/usr/bin/ipython")IPython 0.10.2 -- An enhanced Interactive Python.In [1]: from gdb import *In [2]: vm = parse_and_eval("ruby_current_vm")In [3]: vmOut[3]: <gdb.Value object at 0x207bb70>In [4]: p vm[main_thread].typestruct rb_thread_struct * 補完処理が壊れたり、単に GDB/Python スクリプト 書くよりバグ率高いですが、変態的な可能性を感じる
  24. 24. おまけ: gdb.rb – GDB/Ruby in Py*https://github.com/tmm1/gdb.rb 「 gdb hooks for MRI/REE (and some for YARV) 」(gdb) b vm_exec if $interactive == 0(gdb) run(gdb) set $interactive = 1 #自己呼び出しのブロック防止(gdb) python execfile("ruby-gdb.py")(gdb) ruby eval Thread.list[#<Thread:0x00000000650cc0 run>](gdb) ruby objects HEAPS 24 SLOTS 9816 実は金曜日に発見して LIVE 2717 (27.68%) かなりへこんだ。 FREE 7099 (72.32%) Ruby 内部の機能をフルに 使って自分自身をデバッグ complex 1 (0.04%) bignum 2 (0.07%)
  25. 25. まとめ1. Ruby のデバッグ・学習に使ってみた2. GDB/Python は強力なツール3.正直わけがわからないよ!「明日の Ruby のために、今夜は Python 」参考文献:・ sourceware.org/gdb/onlinedocs/gdb/Python-API.html・ sourceware.org/gdb/wiki/PythonGdbTutorial・ gcc.gnu.org/svn/gcc/trunk/libstdc++-v3/python/

×