Class: Oracle

Inherits:
Object
  • Object
show all
Includes:
Logging
Defined in:
lib/oracle.rb

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logging

included, logger, #logger, logger=

Constructor Details

#initialize(smali_dir, driver, include_types, exclude_types, disable_plugins) ⇒ Oracle

Returns a new instance of Oracle.



8
9
10
11
12
13
14
# File 'lib/oracle.rb', line 8

def initialize(smali_dir, driver, include_types, exclude_types, disable_plugins)
  @smali_files = Oracle.parse_smali(smali_dir)
  @methods = Oracle.filter_methods(@smali_files, include_types, exclude_types)
  Plugin.init_plugins(driver, @smali_files, @methods)
  @disable_plugins = disable_plugins
  logger.info("Disabled plugins: #{@disable_plugins * ','}") unless @disable_plugins.empty?
end

Class Method Details

.enumerate_files(dir, ext) ⇒ Object



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/oracle.rb', line 57

def self.enumerate_files(dir, ext)
  # On Windows, filenames with unicode characters do not show up with Dir#glob or Dir#[]
  # They do, however, show up with Dir.entries, which is fine because it seems to be
  # the only Dir method that let's me set UTF-8 encoding. I must be missing something.
  # OH WELL. Do it the hard way.
  opts = { encoding: 'UTF-8' }
  Dir.entries(dir, opts).collect do |entry|
    next if entry == '.' or entry == '..'
    full_path = "#{dir}/#{entry}"
    if File.directory?(full_path)
      Oracle.enumerate_files(full_path, ext)
    else
      full_path if entry.downcase.end_with?(ext)
    end
  end.flatten.compact
end

.filter_methods(smali_files, include_types, exclude_types) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/oracle.rb', line 41

def self.filter_methods(smali_files, include_types, exclude_types)
  methods = []
  smali_files.each do |smali_file|
    smali_file.methods.each do |method|
      if include_types
        next if method.descriptor !~ include_types
      elsif exclude_types && !(method.descriptor !~ exclude_types)
        next
      end
      methods << method
    end
  end

  methods
end

.parse_smali(smali_dir) ⇒ Object



74
75
76
77
# File 'lib/oracle.rb', line 74

def self.parse_smali(smali_dir)
  file_paths = Oracle.enumerate_files(smali_dir, '.smali')
  smali_files = file_paths.collect { |path| SmaliFile.new(path) }
end

Instance Method Details

#divineObject



16
17
18
19
20
21
22
23
24
25
# File 'lib/oracle.rb', line 16

def divine
  puts "Optimizing #{@methods.size} methods over #{@smali_files.size} Smali files."
  made_changes = process_plugins
  @smali_files.each(&:update) if made_changes
  optimizations = {}
  optimizations = Plugin.plugins.collect { |plugin| plugin.optimizations }
  optimizations = optimizations.inject(Hash.new(0)) { |memo, subhash| subhash.each { |prod, value| memo[prod] += value } ; memo }
  opt_str = optimizations.collect { |k, v| "#{k}=#{v}" } * ', '
  puts "Optimizations: #{opt_str}"
end

#process_pluginsObject



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/oracle.rb', line 27

def process_plugins
  made_changes = false
  loop do
    sweep_changes = false
    Plugin.plugins.each do |p|
      next if @disable_plugins.include?(p.class.name.downcase)
      sweep_changes |= p.process
    end
    made_changes |= sweep_changes
    break unless sweep_changes
  end
  made_changes
end