Decompiler for YARV bytecode.
Pull request Compare This branch is 7 commits behind michaeledgar:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
spec
.document
.gitignore
LICENSE
README.markdown
Rakefile
VERSION
iseq.c.patch

README.markdown

reversal

Best result so far:

This is the best test so far for a complicated decompilation. Reversal turns this:

module Hello
  include SomeModule
  class World < Universe
    attr_accessor :name
    self.attr_writer :moons
    def initialize(some_thing, silly_arg = some_thing.to_s, *args)
      super
      @name = some_thing.to_s
    end

    def orbit!(optional_arg = 10, required_arg, &blk)
      @moons.each do |moon|
        if moon.spherical(:not_cube => true)
          moon.rotate
        else
          moon.cubify
        end
        moon.revolve! :twice
        class << moon
          def crash_into(other_planet)
            other_planet.go_boom!
          end
        end
        yield
      end
    end
  end
end

into this (indentation is generated by the gem):

module Hello
  include(SomeModule)
  class World < Universe
    attr_accessor(:name)
    self.attr_writer(:moons)
    def initialize(some_thing, silly_arg = some_thing.to_s, *args)
      super
      @name = some_thing.to_s
    end
    def orbit!(optional_arg = 10, required_arg, &blk)
      @moons.each do |moon|
        if moon.spherical({:not_cube => true})
          moon.rotate
        else
          moon.cubify
        end
        moon.revolve!(:twice)
        class << moon
          def crash_into(other_planet)
            other_planet.go_boom!
          end
        end
        yield
      end
    end
  end
end

You will need a tiny patch to your interpreter for this to work. I will be petitioning for this to be added to Ruby 1.9.2. The patch should be applied to iseq.c.

Index: iseq.c
===================================================================
--- iseq.c  (revision 26813)
+++ iseq.c  (working copy)
@@ -1004,6 +1004,31 @@
 }

 static VALUE
+iseq_s_get_from_method(VALUE klass, VALUE body)
+{
+    VALUE ret = Qnil;
+    rb_iseq_t *iseq;
+    extern rb_iseq_t *rb_method_get_iseq(VALUE body);
+
+    rb_secure(1);
+
+    if (rb_obj_is_proc(body)) {
+   rb_proc_t *proc;
+   VALUE iseqval;
+   GetProcPtr(body, proc);
+   iseqval = proc->block.iseq->self;
+   if (RUBY_VM_NORMAL_ISEQ_P(iseqval)) {
+        ret = iseqval;
+   }
+    }
+    else if ((iseq = rb_method_get_iseq(body)) != 0) {
+   ret = iseq->self;
+    }
+
+    return ret;
+}
+
+static VALUE
 iseq_s_disasm(VALUE klass, VALUE body)
 {
     VALUE ret = Qnil;
@@ -1498,5 +1523,6 @@
     rb_define_singleton_method(rb_cISeq, "compile_option=", iseq_s_compile_option_set, 1);
     rb_define_singleton_method(rb_cISeq, "disasm", iseq_s_disasm, 1);
     rb_define_singleton_method(rb_cISeq, "disassemble", iseq_s_disasm, 1);
+    rb_define_singleton_method(rb_cISeq, "from_method", iseq_s_get_from_method, 1);
 }

Note on Patches/Pull Requests

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

Copyright

Copyright (c) 2010 Michael Edgar. See LICENSE for details.