class SystemNavigation::InstructionStream::Decoder
Public Class Methods
new(scanner)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 4 def initialize(scanner) @scanner = scanner end
Public Instance Methods
cvar_read_scan(cvar)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 57 def cvar_read_scan(cvar) self.select_instructions(literal: cvar) do |_prev_prev, prev, instruction| next instruction if instruction.reads_cvar?(cvar) end end
cvar_write_scan(cvar)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 63 def cvar_write_scan(cvar) self.select_instructions(literal: cvar) do |prev_prev, prev, instruction| next instruction if instruction.writes_cvar?(cvar) end end
gvar_read_scan(gvar)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 45 def gvar_read_scan(gvar) self.select_instructions(literal: gvar) do |_prev_prev, prev, instruction| next instruction if instruction.reads_gvar?(gvar) end end
gvar_write_scan(gvar)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 51 def gvar_write_scan(gvar) self.select_instructions(literal: gvar) do |prev_prev, prev, instruction| next instruction if instruction.writes_gvar?(gvar) end end
ivar_read_scan(ivar)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 25 def ivar_read_scan(ivar) self.select_instructions(literal: ivar) do |_prev_prev, prev, instruction| next instruction if instruction.reads_ivar?(ivar) if instruction.dynamically_reads_ivar? && prev.putobjects?(ivar) next instruction end end end
ivar_write_scan(ivar)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 35 def ivar_write_scan(ivar) self.select_instructions(literal: ivar) do |prev_prev, prev, instruction| next instruction if instruction.writes_ivar?(ivar) if instruction.dynamically_writes_ivar? && prev_prev.putobjects?(ivar) next instruction end end end
literal_scan(literal)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 69 def literal_scan(literal) name = @scanner.method.original_name self.select_instructions(method_name: name, literal: literal) do |_prev_prev, prev, instruction| if instruction.putobjects?(literal) || instruction.putnils?(literal) || instruction.duparrays?(literal) || instruction.putstrings?(literal) next instruction end end end
msg_send_scan(message)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 82 def msg_send_scan(message) self.select_instructions(literal: message) do |_prev_prev, prev, instruction| next instruction if instruction.sends_msg?(message) end end
scan_for_sent_messages()
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 88 def scan_for_sent_messages @scanner.iseqs(nil).map do |instruction| instruction.find_message end.compact end
select_instructions(literal:, method_name: nil, &block)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 8 def select_instructions(literal:, method_name: nil, &block) instructions = @scanner.iseqs(method_name || literal) instructions.select.with_index do |instruction, i| prev = instructions[i - 1] prev_prev = instructions[i - 2] returned = block.call(prev_prev, prev, instruction) next instruction if returned next if !(instruction.evals? && prev.putstrings?(literal)) self.class.new(iseq_from_eval(prev, @scanner.method)). __send__(block.binding.eval('__method__'), literal).any? end end
Private Instance Methods
iseq_from_eval(instruction, method = nil)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 96 def iseq_from_eval(instruction, method = nil) # Avoid segfault if evaling_str is nil. # See: https://bugs.ruby-lang.org/issues/11159 uncompiled = unwind_eval(instruction.evaling_str || nil.to_s) uncompiled.gsub!(/\\n/, ?\n) iseq = RubyVM::InstructionSequence.compile(uncompiled).disasm InstructionStream.new(method: method, iseq: iseq) end
sanitize_newlines(eval_string)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 110 def sanitize_newlines(eval_string) eval_string.gsub(/\\n/, ?\n) end
unwind_eval(eval_string)
click to toggle source
# File lib/system_navigation/instruction_stream/decoder.rb, line 106 def unwind_eval(eval_string) eval_string.sub(/\A(eval\(\\?["'])*/, '').sub(/(\\?["']\))*\z/, '') end