Skip to content

Instantly share code, notes, and snippets.

@bawNg
Last active January 19, 2018 22:14
Show Gist options
  • Save bawNg/033a7b83b163980db9707b96351417be to your computer and use it in GitHub Desktop.
Save bawNg/033a7b83b163980db9707b96351417be to your computer and use it in GitHub Desktop.
Getting class names from precompiled Ruby byte code with RubyVM::InstructionSequence
queued_classes = []
queued_classes << [@instructions.to_a[13].select! {|item| item.is_a? Array }]
while true
iterations += 1
instructions, super_class, parent_class = queued_classes.shift
break unless instructions
if instructions[0] == :defineclass
next if instructions[1] == :singletonclass
class_name = parent_class ? :"#{parent_class}::#{instructions[1]}" : instructions[1]
class_info = instructions[2]
info = ClassInfo.new(class_info[5][/\<([^:]+)/, 1], class_name, super_class)
class_instructions = class_info[13]
@classes << info
parent_class = parent_class ? "#{parent_class}::#{class_name}" : class_name
i = 0
class_instructions.each do |instruction|
next unless instruction.is_a? Array
super_class = nil
if instruction[0] == :defineclass
index = i - 2
while index > 1
inst = class_instructions[index]
break unless inst[0] == :getconstant
if super_class
super_class = "#{inst[1]}::#{super_class}"
else
super_class = inst[1].to_s
end
index -= 1
end
end
queued_classes << [instruction, super_class, parent_class]
i += 1
end
else
i = 0
instructions.each do |instruction|
next unless instruction.is_a? Array
super_class = nil
name = instruction[0]
if name == :defineclass
index = i - 2
while index > 1
inst = instructions[index]
break unless inst[0] == :getconstant
if super_class
super_class = "#{inst[1]}::#{super_class}"
else
super_class = inst[1].to_s
end
index -= 1
end
end
queued_classes << [instruction, super_class, parent_class]
i += 1
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment