Как наблюдать байт-код Ruby, выполненный YARV - PullRequest
13 голосов
/ 01 августа 2011

Я бы хотел посмотреть байт-код Ruby, выполненный YARV, после вскрытия.

Как мне это получить?

Кто-то еще здесь сказал, что это невозможно,Однако есть hotruby фреймворк, который, кажется, выполняет байт-код ruby, поэтому я озадачен ...

Большое спасибо!

Ответы [ 3 ]

14 голосов
/ 01 августа 2011

Вы можете очень хорошо скомпилировать кусок кода Ruby в байт-код, используя интерпретатор (конечно, будет работать только Ruby MRI 1.9, поскольку это единственная реализация, использующая виртуальную машину YARV), и получить его Ruby-представление ish:

ruby-1.9.2-p180 :007 > require 'pp'
 => true
ruby-1.9.2-p180 :008 > pp RubyVM::InstructionSequence.compile('puts "hello world"').to_a
["YARVInstructionSequence/SimpleDataFormat",
 1,
 2,
 1,
 {:arg_size=>0, :local_size=>1, :stack_max=>2},
 "<compiled>",
 "<compiled>",
 nil,
 1,
 :top,
 [],
 0,
 [],
 [1,
  [:trace, 1],
  [:putnil],
  [:putstring, "hello world"],
  [:send, :puts, 1, nil, 8, 0],
  [:leave]]]

Это именно то, что делает HotRuby: он использует MRI в качестве синтаксического анализатора и транслятора AST-YARV, а затем просто выполняет код в JavaScript.

Вы можетеполучить байт-код для существующего метода с помощью метода RubyVM::InstructionSequence.disasm.Он ожидает Proc в качестве аргумента, поэтому сначала преобразуйте ваш метод в блок, используя object.method(:name).to_proc.

Я не совсем уверен, что вы подразумеваете под «посмертным».В обработчике исключений?После того, как Ruby потерпел крах с SEGV?Последнее вряд ли возможно из-за неспособности поврежденного интерпретатора успешно выполнить любой код Ruby.Для этого вам нужно будет создать расширение C и делать много грязных хаков.Использование этого трюка в обработчике исключений вполне возможно, через.

2 голосов
/ 01 августа 2011

Насколько я понимаю, RubyVM::InstructionSequence.compile - это то, что вам нужно.

0 голосов
/ 03 февраля 2019

Чтобы получить более читаемый вывод, вы можете использовать disasm после compile

[17] pry(main)> code = <<STR
[17] pry(main)* puts "Hello World"
[17] pry(main)* STR
=> "puts \"Hello World\"\n"
[19] pry(main)> puts RubyVM::InstructionSequence.compile(code).disasm
== disasm: <RubyVM::InstructionSequence:<compiled>@<compiled>>==========
0000 trace            1                                               (   1)
0002 putself
0003 putstring        "Hello World"
0005 opt_send_without_block <callinfo!mid:puts, argc:1, FCALL|ARGS_SIMPLE>
0007 leave
=> nil
[20] pry(main)>
...