Hacking Ruby with Python
Upcoming SlideShare
Loading in...5
×
 

Hacking Ruby with Python

on

  • 2,129 views

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

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.

Statistics

Views

Total Views
2,129
Views on SlideShare
2,129
Embed Views
0

Actions

Likes
2
Downloads
14
Comments
0

0 Embeds 0

No embeds

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Hacking Ruby with Python Hacking Ruby with Python Presentation Transcript

  • Hacking Ruby with Python @tyamadajp
  • 光ある所、影がありコードある所、闇がある
  • 闇の名は、バグ。そしてバグを殺す者、
  • Ruby Debugger~僕と契約して闇デバッガになろうよ!~
  • みなさんオススメのデバッガは?0. p+? (?!)1. debug.rb? (旧型)2. ruby-debug? (普通)3. rb-trepanning? (新型)4. others?#ベースの機能を生かした# JRuby, Rubinius 用のとかも#ありますよね
  • デバッガのいい所・どこまでも覗ける・動いている状態を覗ける・あろうことか、手まで出せる「言語仕様?そんなの関係ねぇ!」「もし闇の住人がデバッガーの       解説ページを読んだら」
  • さて今宵のデバッガは・・・
  • さて今宵のデバッガは・・・ GDB
  • さて今宵のデバッガは・・・ The GNU Debugger
  • さて今宵のデバッガは・・・… の Python 拡張
  • さて今宵のデバッガは・・・ GDB/Python 明日の Ruby のために、 今夜は Python
  • なにそれこわい
  • こわくないよ!> GDB/Python1. GDB を 100% API control → ブレークポイントの操作とか2. GDB そのものも拡張 →新コマンド追加 / (gdb)... →簡易関数の追加 / $func(...) → print ハイジャック / pretty printer
  • こんな感じ(実装例)(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 ・・・まあ色々デコードしてくれます
  • それ $RUBY/.gdbinit でできるよ?ええ、あるのですが・・・・主力は内蔵 eval や dump 関数?・なので展開能力が控えめ ( ぬるぽ避け? )  (gdb) rp recv  T_CLASS: $1156 = (struct RClass *) 0x655310      →ソース読解の道具が欲しかった      →自分でデコードするのがよい練習
  • ぬるぽを恐れず何でも展開(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 … 中身を徹底表示
  • GDB script ではダメですか?・ まともな制御構文がない → if else if else if else end end end・ スコープ概念が(ほとんど)ない・ 遅い。当人比で最大 100+ 倍以上・ 限りなく貧弱なデータ操作機能とライブラリ     「 GDB script がやられたか・・・」     「所詮あやつは言語以前の存在」
  • 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))
  • 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”) などで
  • 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% カット!
  • 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 にも 本気で欲しくなったり ※ スライドに収めるため機能とコードをカットしています。バグってたらごめんなさい
  • 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) 表示処理に適用される
  • おまけ: 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 スクリプト 書くよりバグ率高いですが、変態的な可能性を感じる
  • おまけ: 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%)
  • まとめ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/