furnace-avm2 0.9.0 → 0.9.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +2 -2
- data/bin/furnace-avm2 +5 -1
- data/bin/furnace-avm2-decompiler +80 -13
- data/bin/furnace-avm2-shell +32 -0
- data/furnace-avm2.gemspec +1 -1
- data/lib/furnace-avm2/abc.rb +1 -7
- data/lib/furnace-avm2/abc/metadata/file.rb +65 -0
- data/lib/furnace-avm2/abc/metadata/instance_info.rb +17 -11
- data/lib/furnace-avm2/abc/metadata/metadata_info.rb +14 -4
- data/lib/furnace-avm2/abc/metadata/method_body_info.rb +11 -3
- data/lib/furnace-avm2/abc/metadata/method_info.rb +3 -4
- data/lib/furnace-avm2/abc/metadata/multiname_kind_genericname.rb +3 -2
- data/lib/furnace-avm2/abc/metadata/multiname_kind_multiname.rb +11 -2
- data/lib/furnace-avm2/abc/metadata/multiname_kind_multinamel.rb +4 -0
- data/lib/furnace-avm2/abc/metadata/multiname_kind_qname.rb +10 -2
- data/lib/furnace-avm2/abc/metadata/multiname_kind_rtqname.rb +4 -0
- data/lib/furnace-avm2/abc/metadata/multiname_kind_rtqnamel.rb +4 -0
- data/lib/furnace-avm2/abc/metadata/script_info.rb +11 -7
- data/lib/furnace-avm2/abc/metadata/trait_class.rb +2 -2
- data/lib/furnace-avm2/abc/metadata/trait_info.rb +1 -1
- data/lib/furnace-avm2/abc/metadata/trait_method.rb +4 -3
- data/lib/furnace-avm2/abc/metadata/trait_slot.rb +2 -2
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_extend_1.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_extend_16.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_extend_8.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_load_float32.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_load_float64.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_load_int16.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_load_int32.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_load_int8.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_store_float32.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_store_float64.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_store_int16.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_store_int32.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/alchemy/alchemy_store_int8.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_add.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_add_i.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_declocal.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_declocal_i.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_decrement.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_decrement_i.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_divide.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_equals.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_greaterequals.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_greaterthan.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_inclocal.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_inclocal_i.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_increment.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_increment_i.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_lessequals.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_lessthan.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_modulo.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_multiply.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_multiply_i.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_negate.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_negate_i.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_not.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_strictequals.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_subtract.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/arithmetic/as3_subtract_i.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/bitwise/as3_bitand.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/bitwise/as3_bitnot.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/bitwise/as3_bitor.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/bitwise/as3_bitxor.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/bitwise/as3_lshift.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/bitwise/as3_rshift.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/bitwise/as3_urshift.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/control_transfer/as3_lookupswitch.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/control_transfer_opcode.rb +0 -4
- data/lib/furnace-avm2/abc/opcodes/exception/as3_newcatch.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/function_invocation/as3_callproplex.rb +4 -0
- data/lib/furnace-avm2/abc/opcodes/function_invocation_opcode.rb +4 -0
- data/lib/furnace-avm2/abc/opcodes/function_return/as3_returnvalue.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/function_return/as3_returnvoid.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/generic/as3_escxattr.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/generic/as3_escxelem.rb +8 -0
- data/lib/furnace-avm2/abc/opcodes/generic/as3_getlex.rb +4 -0
- data/lib/furnace-avm2/abc/opcodes/object_manipulation/as3_newfunction.rb +5 -1
- data/lib/furnace-avm2/abc/opcodes/property/as3_constructprop.rb +4 -0
- data/lib/furnace-avm2/abc/opcodes/property_opcode.rb +4 -0
- data/lib/furnace-avm2/abc/opcodes/push_literal/as3_pushuint.rb +11 -0
- data/lib/furnace-avm2/abc/opcodes/type_conversion/as3_applytype.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/type_conversion/as3_coerce.rb +5 -1
- data/lib/furnace-avm2/abc/opcodes/type_conversion/as3_coerce_a.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/type_conversion/as3_coerce_b.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/type_conversion/as3_coerce_s.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/type_conversion/as3_convert_d.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/type_conversion/as3_convert_i.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/type_conversion/as3_convert_o.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/type_conversion/as3_convert_s.rb +1 -1
- data/lib/furnace-avm2/abc/opcodes/type_conversion/as3_convert_u.rb +1 -1
- data/lib/furnace-avm2/abc/primitives/opcode_sequence.rb +35 -23
- data/lib/furnace-avm2/abc/primitives/record.rb +11 -0
- data/lib/furnace-avm2/binary/record.rb +9 -7
- data/lib/furnace-avm2/source/declaration_tokens/callee_token.rb +8 -5
- data/lib/furnace-avm2/source/declaration_tokens/class_implementations_token.rb +5 -1
- data/lib/furnace-avm2/source/declaration_tokens/class_specifiers_token.rb +2 -1
- data/lib/furnace-avm2/source/declaration_tokens/class_token.rb +5 -1
- data/lib/furnace-avm2/source/declaration_tokens/metadata_token.rb +25 -0
- data/lib/furnace-avm2/source/declaration_tokens/method_specifiers_token.rb +4 -3
- data/lib/furnace-avm2/source/declaration_tokens/method_token.rb +1 -0
- data/lib/furnace-avm2/source/declaration_tokens/multiname_token.rb +28 -13
- data/lib/furnace-avm2/source/declaration_tokens/package_token.rb +9 -8
- data/lib/furnace-avm2/source/declaration_tokens/scope_token.rb +2 -0
- data/lib/furnace-avm2/source/declaration_tokens/script_token.rb +4 -1
- data/lib/furnace-avm2/source/declaration_tokens/slot_token.rb +1 -0
- data/lib/furnace-avm2/source/declaration_tokens/specifiers_token.rb +11 -9
- data/lib/furnace-avm2/source/decompiler.rb +372 -101
- data/lib/furnace-avm2/source/implementation_tokens/closure_name_token.rb +7 -0
- data/lib/furnace-avm2/source/implementation_tokens/closure_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/instance_of_token.rb +9 -0
- data/lib/furnace-avm2/source/implementation_tokens/supplementary_comment_token.rb +16 -0
- data/lib/furnace-avm2/source/implementation_tokens/xml_literal_token.rb +14 -0
- data/lib/furnace-avm2/transform/ast_build.rb +3 -2
- data/lib/furnace-avm2/transform/ast_normalize.rb +39 -7
- data/lib/furnace-avm2/transform/cfg_build.rb +16 -6
- data/lib/furnace-avm2/transform/cfg_reduce.rb +4 -3
- data/lib/furnace-avm2/transform/nf_normalize.rb +15 -7
- data/lib/furnace-avm2/version.rb +1 -1
- data/test/basic.as +15 -0
- data/test/global.as +11 -0
- metadata +46 -29
- data/bin/furnace-avm2-benchmark +0 -38
- data/lib/furnace-avm2/abc/opcodes/arithmetic_opcode.rb +0 -4
- data/lib/furnace-avm2/abc/opcodes/bitwise_opcode.rb +0 -4
- data/lib/furnace-avm2/abc/opcodes/exception_opcode.rb +0 -4
- data/lib/furnace-avm2/abc/opcodes/function_return_opcode.rb +0 -4
- data/lib/furnace-avm2/abc/opcodes/object_manipulation_opcode.rb +0 -4
- data/lib/furnace-avm2/abc/opcodes/type_conversion_opcode.rb +0 -4
data/Gemfile.lock
CHANGED
data/bin/furnace-avm2
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require "rubygems"
|
4
|
-
require "bundler/setup"
|
5
4
|
|
6
5
|
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
7
6
|
|
@@ -38,6 +37,7 @@ EOS
|
|
38
37
|
opt :cfg, "Emit CFG in Graphviz format for methods", :default => false, :short => '-C'
|
39
38
|
|
40
39
|
opt :dce, "Eliminate dead code", :default => false
|
40
|
+
opt :fix_names, "Remove invalid characters from names", :default => true, :short => '-q'
|
41
41
|
opt :ast, "Build AST", :default => false
|
42
42
|
opt :nf, "Build NF-AST", :default => false
|
43
43
|
opt :decompile, "Decompile methods", :default => false
|
@@ -77,6 +77,10 @@ failed = []
|
|
77
77
|
dced = []
|
78
78
|
smallest = nil
|
79
79
|
|
80
|
+
if opts[:fix_names]
|
81
|
+
abc.fix_names!
|
82
|
+
end
|
83
|
+
|
80
84
|
if opts[:grep]
|
81
85
|
regexp = Regexp.new(opts[:grep])
|
82
86
|
|
data/bin/furnace-avm2-decompiler
CHANGED
@@ -33,6 +33,8 @@ EOS
|
|
33
33
|
opt :except, "Operate on all classes except <s+>", :type => :strings, :short => '-E'
|
34
34
|
opt :grep, "Search <s> (regexp) in class names", :type => :string, :short => '-G'
|
35
35
|
|
36
|
+
opt :no_output, "Don't write out any code", :default => false
|
37
|
+
|
36
38
|
opt :decompile, "Write ActionScript 3 code", :type => :boolean, :short => '-d'
|
37
39
|
opt :destructurize, "Write internal token structure", :type => :boolean, :short => '-s'
|
38
40
|
end
|
@@ -84,6 +86,19 @@ if opts[:grep]
|
|
84
86
|
exit
|
85
87
|
end
|
86
88
|
|
89
|
+
global_slots = {}
|
90
|
+
|
91
|
+
abc.scripts.each do |script|
|
92
|
+
(script.slot_traits + script.const_traits).each do |trait|
|
93
|
+
next if trait.idx == 0
|
94
|
+
global_slots[trait.idx] = trait
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
decompile_options[:global_slots] = global_slots
|
99
|
+
|
100
|
+
start_time = Time.now
|
101
|
+
|
87
102
|
mutex = Mutex.new
|
88
103
|
|
89
104
|
roots = {}
|
@@ -92,7 +107,32 @@ total_size = workqueue.size
|
|
92
107
|
|
93
108
|
last_percentage = 0
|
94
109
|
|
95
|
-
|
110
|
+
stat = {
|
111
|
+
total: 0,
|
112
|
+
success: 0,
|
113
|
+
partial: 0,
|
114
|
+
failed: 0,
|
115
|
+
}
|
116
|
+
|
117
|
+
$stderr.puts "Found #{total_size} classes and packages."
|
118
|
+
|
119
|
+
stick = %w(| / - \\)
|
120
|
+
stick_state = 0
|
121
|
+
stick_timer = 0
|
122
|
+
|
123
|
+
progress_thread = Thread.new do
|
124
|
+
loop do
|
125
|
+
stick_timer += 1
|
126
|
+
if stick_timer % 10 == 0
|
127
|
+
$stderr.print "\e[KDecompiling... #{total_size - workqueue.size}/#{total_size} "
|
128
|
+
$stderr.print stick[stick_state]
|
129
|
+
$stderr.print "\e[0G"
|
130
|
+
stick_state = (stick_state + 1) % stick.count
|
131
|
+
end
|
132
|
+
|
133
|
+
sleep
|
134
|
+
end
|
135
|
+
end
|
96
136
|
|
97
137
|
opts[:threads].times.map do
|
98
138
|
Thread.new do
|
@@ -100,12 +140,6 @@ opts[:threads].times.map do
|
|
100
140
|
what = nil
|
101
141
|
mutex.synchronize do
|
102
142
|
what = workqueue.pop
|
103
|
-
|
104
|
-
percentage = (total_size - workqueue.size) * 100 / total_size
|
105
|
-
if percentage >= last_percentage
|
106
|
-
$stderr.print " #{percentage}% (#{total_size - workqueue.size}) "
|
107
|
-
last_percentage += 10
|
108
|
-
end
|
109
143
|
end
|
110
144
|
|
111
145
|
break if what.nil?
|
@@ -119,23 +153,56 @@ opts[:threads].times.map do
|
|
119
153
|
end
|
120
154
|
next if shound_skip.(name)
|
121
155
|
|
122
|
-
|
156
|
+
options = decompile_options.merge(
|
157
|
+
stat: {
|
158
|
+
total: 0,
|
159
|
+
success: 0,
|
160
|
+
partial: 0,
|
161
|
+
failed: 0,
|
162
|
+
}
|
163
|
+
)
|
164
|
+
|
165
|
+
source = what.decompile(options)
|
123
166
|
next unless source
|
124
167
|
|
125
168
|
text = source.to_text
|
126
169
|
|
127
170
|
mutex.synchronize do
|
128
|
-
|
171
|
+
options[:stat].each do |facet, value|
|
172
|
+
stat[facet] += value
|
173
|
+
end
|
174
|
+
|
129
175
|
roots[ns.to_s] ||= []
|
130
176
|
roots[ns.to_s] << text
|
177
|
+
|
178
|
+
progress_thread.wakeup
|
131
179
|
end
|
132
180
|
end
|
133
181
|
end
|
134
182
|
end.each(&:join)
|
135
183
|
|
136
|
-
|
184
|
+
end_time = Time.now
|
185
|
+
|
186
|
+
if stat[:total] > 0
|
187
|
+
$stderr.puts
|
137
188
|
|
138
|
-
|
139
|
-
|
140
|
-
|
189
|
+
{ "Decompiled" => :success,
|
190
|
+
"Partially decompiled" => :partial,
|
191
|
+
"Failed" => :failed,
|
192
|
+
}.each do |facet_name, facet|
|
193
|
+
$stderr.puts "#{facet_name.rjust(21)}: " \
|
194
|
+
"#{stat[facet]}/#{stat[:total]} " \
|
195
|
+
"(#{(stat[facet].to_f * 100 / stat[:total]).to_i}%)"
|
196
|
+
end
|
197
|
+
else
|
198
|
+
$stderr.puts "No methods were processed."
|
141
199
|
end
|
200
|
+
|
201
|
+
$stderr.puts "Time taken: #{"%.2f" % (end_time - start_time)}s"
|
202
|
+
|
203
|
+
unless opts[:no_output]
|
204
|
+
roots.values.flatten.each do |code|
|
205
|
+
puts code.gsub(/ +$/, '')
|
206
|
+
puts
|
207
|
+
end
|
208
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
|
5
|
+
$: << File.join(File.dirname(__FILE__), '..', 'lib')
|
6
|
+
|
7
|
+
require "furnace-avm2"
|
8
|
+
|
9
|
+
begin
|
10
|
+
gem "pry"
|
11
|
+
require "pry"
|
12
|
+
rescue LoadError
|
13
|
+
puts "$ gem install pry"
|
14
|
+
exit 1
|
15
|
+
end
|
16
|
+
|
17
|
+
include Furnace
|
18
|
+
|
19
|
+
def load_file(filename)
|
20
|
+
File.open(filename) do |file|
|
21
|
+
abc = AVM2::ABC::File.new
|
22
|
+
abc.read(file)
|
23
|
+
abc
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Interactive AVM2 console ready.
|
28
|
+
# Begin with:
|
29
|
+
# > abc = load_file("filename.abc")
|
30
|
+
# Records can be examined via #to_hash.
|
31
|
+
|
32
|
+
binding.pry
|
data/furnace-avm2.gemspec
CHANGED
@@ -17,6 +17,6 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
|
20
|
-
s.add_runtime_dependency "furnace", '>= 0.1.
|
20
|
+
s.add_runtime_dependency "furnace", '>= 0.1.1'
|
21
21
|
s.add_runtime_dependency "trollop"
|
22
22
|
end
|
data/lib/furnace-avm2/abc.rb
CHANGED
@@ -10,18 +10,12 @@ require_relative "abc/primitives/record"
|
|
10
10
|
require_relative "abc/primitives/opcode_sequence"
|
11
11
|
|
12
12
|
require_relative "abc/opcodes/opcode"
|
13
|
-
require_relative "abc/opcodes/contextual_opcode"
|
14
13
|
|
14
|
+
require_relative "abc/opcodes/contextual_opcode"
|
15
15
|
require_relative "abc/opcodes/load_store_opcode"
|
16
|
-
require_relative "abc/opcodes/arithmetic_opcode"
|
17
|
-
require_relative "abc/opcodes/bitwise_opcode"
|
18
|
-
require_relative "abc/opcodes/type_conversion_opcode"
|
19
16
|
require_relative "abc/opcodes/push_literal_opcode"
|
20
17
|
require_relative "abc/opcodes/control_transfer_opcode"
|
21
18
|
require_relative "abc/opcodes/function_invocation_opcode"
|
22
|
-
require_relative "abc/opcodes/function_return_opcode"
|
23
|
-
require_relative "abc/opcodes/exception_opcode"
|
24
|
-
|
25
19
|
require_relative "abc/opcodes/property_opcode"
|
26
20
|
|
27
21
|
Dir[File.join(File.dirname(__FILE__), "abc", "opcodes", "*", "*.rb")].each do |file|
|
@@ -23,5 +23,70 @@ module Furnace::AVM2::ABC
|
|
23
23
|
def root
|
24
24
|
self
|
25
25
|
end
|
26
|
+
|
27
|
+
def method_body_at(index)
|
28
|
+
@method_body_indexes[index]
|
29
|
+
end
|
30
|
+
|
31
|
+
def fix_names!
|
32
|
+
@name_set = Set.new(constant_pool.strings)
|
33
|
+
|
34
|
+
constant_pool.namespaces.each do |ns|
|
35
|
+
fix_name!(ns.name_idx, ns: true)
|
36
|
+
end
|
37
|
+
|
38
|
+
constant_pool.multinames.each do |multiname|
|
39
|
+
if [:QName, :QNameA,
|
40
|
+
:Multiname, :MultinameA,
|
41
|
+
:RTQName, :RTQMameA].include? multiname.kind
|
42
|
+
fix_name!(multiname.data.name_idx)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def fix_name!(name_idx, options={})
|
48
|
+
old_name = constant_pool.strings[name_idx - 1]
|
49
|
+
return if ["", "*"].include? old_name
|
50
|
+
|
51
|
+
fixed_name = sanitize_name(old_name, options)
|
52
|
+
|
53
|
+
if old_name != fixed_name
|
54
|
+
index = 0
|
55
|
+
indexed_name = fixed_name
|
56
|
+
while @name_set.include? indexed_name
|
57
|
+
indexed_name = "#{fixed_name}_i#{index}"
|
58
|
+
index += 1
|
59
|
+
end
|
60
|
+
|
61
|
+
@name_set.add indexed_name
|
62
|
+
|
63
|
+
constant_pool.strings[name_idx - 1] = indexed_name
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def sanitize_name(name, options={})
|
68
|
+
if options[:ns]
|
69
|
+
return name if name.start_with? "http://"
|
70
|
+
|
71
|
+
name.split('.').map do |part|
|
72
|
+
part.gsub(/^[^a-zA-Z_$]+/, '').
|
73
|
+
gsub(/[^a-zA-Z_$0-9:]+/, '')
|
74
|
+
end.reject do |part|
|
75
|
+
part.empty?
|
76
|
+
end.join('.')
|
77
|
+
else
|
78
|
+
name.gsub(/^[^a-zA-Z_$]+/, '').
|
79
|
+
gsub(/[^a-zA-Z_$0-9:]+/, '')
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
protected
|
84
|
+
|
85
|
+
def after_read(io)
|
86
|
+
@method_body_indexes = {}
|
87
|
+
method_bodies.each do |body|
|
88
|
+
@method_body_indexes[body.method_idx] = body
|
89
|
+
end
|
90
|
+
end
|
26
91
|
end
|
27
92
|
end
|
@@ -63,21 +63,27 @@ module Furnace::AVM2::ABC
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def collect_ns
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
66
|
+
options = {
|
67
|
+
ns: Set.new([ name.ns ]),
|
68
|
+
names: { name.name => name.ns },
|
69
|
+
no_ns: Set.new,
|
70
|
+
}
|
71
|
+
|
72
|
+
super_name.collect_ns(options) if super_name
|
73
|
+
initializer.collect_ns(options) if initializer
|
74
|
+
interfaces.each { |iface| iface.collect_ns(options) } # stupid avm2
|
75
|
+
traits.each { |trait| trait.collect_ns(options) }
|
76
|
+
klass.traits.each { |trait| trait.collect_ns(options) }
|
77
|
+
|
78
|
+
options
|
73
79
|
end
|
74
80
|
|
75
81
|
def decompile(options={})
|
76
82
|
Furnace::AVM2::Tokens::PackageToken.new(self,
|
77
|
-
options.merge(
|
78
|
-
|
79
|
-
|
80
|
-
|
83
|
+
options.merge(collect_ns).merge(
|
84
|
+
package_type: (interface? ? :interface : :class),
|
85
|
+
package_name: name)
|
86
|
+
)
|
81
87
|
end
|
82
88
|
end
|
83
89
|
end
|
@@ -1,9 +1,19 @@
|
|
1
1
|
module Furnace::AVM2::ABC
|
2
2
|
class MetadataInfo < Record
|
3
|
-
|
3
|
+
const_ref :name, :string
|
4
4
|
|
5
|
-
vuint30
|
6
|
-
|
7
|
-
|
5
|
+
vuint30 :item_count, :value => lambda { item_keys.count }
|
6
|
+
const_array :item_keys, :string, :initial_length => :item_count
|
7
|
+
const_array :item_values, :string, :initial_length => :item_count
|
8
|
+
|
9
|
+
def to_hash
|
10
|
+
hash = {}
|
11
|
+
|
12
|
+
item_count.times do |n|
|
13
|
+
hash[item_keys[n]] = item_values[n]
|
14
|
+
end
|
15
|
+
|
16
|
+
hash
|
17
|
+
end
|
8
18
|
end
|
9
19
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Furnace::AVM2::ABC
|
2
2
|
class MethodBodyInfo < Record
|
3
|
+
include RecordWithTraits
|
4
|
+
|
3
5
|
root_ref :method
|
4
6
|
vuint30 :max_stack
|
5
7
|
vuint30 :local_count
|
@@ -19,10 +21,10 @@ module Furnace::AVM2::ABC
|
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
22
|
-
def code_to_ast(options={})
|
24
|
+
def code_to_ast(options={ eliminate_nops: true })
|
23
25
|
pipeline = Furnace::Transform::Pipeline.new([
|
24
26
|
Furnace::AVM2::Transform::ASTBuild.new(options),
|
25
|
-
Furnace::AVM2::Transform::ASTNormalize.new
|
27
|
+
Furnace::AVM2::Transform::ASTNormalize.new(options)
|
26
28
|
])
|
27
29
|
|
28
30
|
pipeline.run(code, self)
|
@@ -33,7 +35,7 @@ module Furnace::AVM2::ABC
|
|
33
35
|
Furnace::AVM2::Transform::CFGBuild.new
|
34
36
|
])
|
35
37
|
|
36
|
-
pipeline.run(*code_to_ast)
|
38
|
+
pipeline.run(*code_to_ast({}))
|
37
39
|
end
|
38
40
|
|
39
41
|
def code_to_nf
|
@@ -48,5 +50,11 @@ module Furnace::AVM2::ABC
|
|
48
50
|
def decompile(options={})
|
49
51
|
Furnace::AVM2::Decompiler.new(self, options).decompile
|
50
52
|
end
|
53
|
+
|
54
|
+
def collect_ns(options)
|
55
|
+
code.each do |opcode|
|
56
|
+
opcode.collect_ns(options) if opcode.respond_to? :collect_ns
|
57
|
+
end
|
58
|
+
end
|
51
59
|
end
|
52
60
|
end
|
@@ -55,10 +55,9 @@ module Furnace::AVM2::ABC
|
|
55
55
|
root.normalize_hierarchy!
|
56
56
|
end
|
57
57
|
|
58
|
-
def collect_ns
|
59
|
-
|
60
|
-
|
61
|
-
ns
|
58
|
+
def collect_ns(options)
|
59
|
+
param_types.compact.each { |type| type.collect_ns(options) }
|
60
|
+
return_type.collect_ns(options) if return_type
|
62
61
|
end
|
63
62
|
end
|
64
63
|
end
|
@@ -12,8 +12,9 @@ module Furnace::AVM2::ABC
|
|
12
12
|
AST::Node.new(:generic, [ name.to_astlet, parameters.map(&:to_astlet) ])
|
13
13
|
end
|
14
14
|
|
15
|
-
def collect_ns
|
16
|
-
|
15
|
+
def collect_ns(options)
|
16
|
+
name.collect_ns(options)
|
17
|
+
parameters.each { |type| type.collect_ns(options) }
|
17
18
|
end
|
18
19
|
end
|
19
20
|
end
|
@@ -11,8 +11,17 @@ module Furnace::AVM2::ABC
|
|
11
11
|
AST::Node.new(:m, [ ns_set.to_astlet, name ])
|
12
12
|
end
|
13
13
|
|
14
|
-
def collect_ns
|
15
|
-
ns_set.ns
|
14
|
+
def collect_ns(options)
|
15
|
+
ns = ns_set.ns[0]
|
16
|
+
return if options[:no_ns].include?(ns)
|
17
|
+
|
18
|
+
names = options[:names]
|
19
|
+
if names[name].nil?
|
20
|
+
options[:ns].add ns
|
21
|
+
names[name] = ns
|
22
|
+
elsif names[name] != ns
|
23
|
+
options[:no_ns].add ns
|
24
|
+
end
|
16
25
|
end
|
17
26
|
|
18
27
|
def context_size
|