furnace-avm2 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (201) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +17 -0
  4. data/abcdump.abc +0 -0
  5. data/bin/furnace-avm2 +175 -0
  6. data/bin/furnace-avm2-benchmark +38 -0
  7. data/darkorbit.abc +0 -0
  8. data/furnace-avm2.gemspec +22 -0
  9. data/lib/avm2.rb +13 -0
  10. data/lib/avm2/abc.rb +65 -0
  11. data/lib/avm2/abc/metadata/const_pool_info.rb +18 -0
  12. data/lib/avm2/abc/metadata/exception_info.rb +29 -0
  13. data/lib/avm2/abc/metadata/file.rb +27 -0
  14. data/lib/avm2/abc/metadata/instance_info.rb +53 -0
  15. data/lib/avm2/abc/metadata/klass_info.rb +7 -0
  16. data/lib/avm2/abc/metadata/metadata_info.rb +9 -0
  17. data/lib/avm2/abc/metadata/method_body_info.rb +31 -0
  18. data/lib/avm2/abc/metadata/method_info.rb +57 -0
  19. data/lib/avm2/abc/metadata/multiname_info.rb +42 -0
  20. data/lib/avm2/abc/metadata/multiname_kind_genericname.rb +16 -0
  21. data/lib/avm2/abc/metadata/multiname_kind_multiname.rb +18 -0
  22. data/lib/avm2/abc/metadata/multiname_kind_multinamel.rb +17 -0
  23. data/lib/avm2/abc/metadata/multiname_kind_qname.rb +44 -0
  24. data/lib/avm2/abc/metadata/multiname_kind_rtqname.rb +17 -0
  25. data/lib/avm2/abc/metadata/multiname_kind_rtqnamel.rb +11 -0
  26. data/lib/avm2/abc/metadata/namespace_info.rb +22 -0
  27. data/lib/avm2/abc/metadata/ns_set_info.rb +13 -0
  28. data/lib/avm2/abc/metadata/option_detail.rb +26 -0
  29. data/lib/avm2/abc/metadata/option_info.rb +5 -0
  30. data/lib/avm2/abc/metadata/script_info.rb +7 -0
  31. data/lib/avm2/abc/metadata/trait_class.rb +9 -0
  32. data/lib/avm2/abc/metadata/trait_function.rb +9 -0
  33. data/lib/avm2/abc/metadata/trait_info.rb +55 -0
  34. data/lib/avm2/abc/metadata/trait_method.rb +12 -0
  35. data/lib/avm2/abc/metadata/trait_slot.rb +11 -0
  36. data/lib/avm2/abc/opcodes/arithmetic/as3_add.rb +8 -0
  37. data/lib/avm2/abc/opcodes/arithmetic/as3_add_i.rb +10 -0
  38. data/lib/avm2/abc/opcodes/arithmetic/as3_declocal.rb +14 -0
  39. data/lib/avm2/abc/opcodes/arithmetic/as3_declocal_i.rb +14 -0
  40. data/lib/avm2/abc/opcodes/arithmetic/as3_decrement.rb +10 -0
  41. data/lib/avm2/abc/opcodes/arithmetic/as3_decrement_i.rb +10 -0
  42. data/lib/avm2/abc/opcodes/arithmetic/as3_divide.rb +10 -0
  43. data/lib/avm2/abc/opcodes/arithmetic/as3_equals.rb +8 -0
  44. data/lib/avm2/abc/opcodes/arithmetic/as3_greaterequals.rb +8 -0
  45. data/lib/avm2/abc/opcodes/arithmetic/as3_greaterthan.rb +8 -0
  46. data/lib/avm2/abc/opcodes/arithmetic/as3_inclocal.rb +14 -0
  47. data/lib/avm2/abc/opcodes/arithmetic/as3_inclocal_i.rb +18 -0
  48. data/lib/avm2/abc/opcodes/arithmetic/as3_increment.rb +10 -0
  49. data/lib/avm2/abc/opcodes/arithmetic/as3_increment_i.rb +10 -0
  50. data/lib/avm2/abc/opcodes/arithmetic/as3_lessequals.rb +8 -0
  51. data/lib/avm2/abc/opcodes/arithmetic/as3_lessthan.rb +8 -0
  52. data/lib/avm2/abc/opcodes/arithmetic/as3_modulo.rb +10 -0
  53. data/lib/avm2/abc/opcodes/arithmetic/as3_multiply.rb +10 -0
  54. data/lib/avm2/abc/opcodes/arithmetic/as3_multiply_i.rb +10 -0
  55. data/lib/avm2/abc/opcodes/arithmetic/as3_negate.rb +10 -0
  56. data/lib/avm2/abc/opcodes/arithmetic/as3_negate_i.rb +10 -0
  57. data/lib/avm2/abc/opcodes/arithmetic/as3_not.rb +8 -0
  58. data/lib/avm2/abc/opcodes/arithmetic/as3_strictequals.rb +8 -0
  59. data/lib/avm2/abc/opcodes/arithmetic/as3_subtract.rb +10 -0
  60. data/lib/avm2/abc/opcodes/arithmetic/as3_subtract_i.rb +10 -0
  61. data/lib/avm2/abc/opcodes/arithmetic_opcode.rb +4 -0
  62. data/lib/avm2/abc/opcodes/bitwise/as3_bitand.rb +8 -0
  63. data/lib/avm2/abc/opcodes/bitwise/as3_bitnot.rb +8 -0
  64. data/lib/avm2/abc/opcodes/bitwise/as3_bitor.rb +8 -0
  65. data/lib/avm2/abc/opcodes/bitwise/as3_bitxor.rb +8 -0
  66. data/lib/avm2/abc/opcodes/bitwise/as3_lshift.rb +8 -0
  67. data/lib/avm2/abc/opcodes/bitwise/as3_rshift.rb +8 -0
  68. data/lib/avm2/abc/opcodes/bitwise/as3_urshift.rb +8 -0
  69. data/lib/avm2/abc/opcodes/bitwise_opcode.rb +4 -0
  70. data/lib/avm2/abc/opcodes/contextual_opcode.rb +32 -0
  71. data/lib/avm2/abc/opcodes/control_transfer/as3_ifeq.rb +14 -0
  72. data/lib/avm2/abc/opcodes/control_transfer/as3_iffalse.rb +14 -0
  73. data/lib/avm2/abc/opcodes/control_transfer/as3_ifge.rb +14 -0
  74. data/lib/avm2/abc/opcodes/control_transfer/as3_ifgt.rb +14 -0
  75. data/lib/avm2/abc/opcodes/control_transfer/as3_ifle.rb +14 -0
  76. data/lib/avm2/abc/opcodes/control_transfer/as3_iflt.rb +14 -0
  77. data/lib/avm2/abc/opcodes/control_transfer/as3_ifne.rb +14 -0
  78. data/lib/avm2/abc/opcodes/control_transfer/as3_ifnge.rb +14 -0
  79. data/lib/avm2/abc/opcodes/control_transfer/as3_ifngt.rb +14 -0
  80. data/lib/avm2/abc/opcodes/control_transfer/as3_ifnle.rb +14 -0
  81. data/lib/avm2/abc/opcodes/control_transfer/as3_ifnlt.rb +14 -0
  82. data/lib/avm2/abc/opcodes/control_transfer/as3_ifstricteq.rb +14 -0
  83. data/lib/avm2/abc/opcodes/control_transfer/as3_ifstrictne.rb +14 -0
  84. data/lib/avm2/abc/opcodes/control_transfer/as3_iftrue.rb +14 -0
  85. data/lib/avm2/abc/opcodes/control_transfer/as3_jump.rb +22 -0
  86. data/lib/avm2/abc/opcodes/control_transfer/as3_lookupswitch.rb +34 -0
  87. data/lib/avm2/abc/opcodes/control_transfer_opcode.rb +37 -0
  88. data/lib/avm2/abc/opcodes/exception/as3_newcatch.rb +16 -0
  89. data/lib/avm2/abc/opcodes/exception_opcode.rb +4 -0
  90. data/lib/avm2/abc/opcodes/function_invocation/as3_call.rb +16 -0
  91. data/lib/avm2/abc/opcodes/function_invocation/as3_callproperty.rb +7 -0
  92. data/lib/avm2/abc/opcodes/function_invocation/as3_callpropvoid.rb +7 -0
  93. data/lib/avm2/abc/opcodes/function_invocation/as3_callsuper.rb +7 -0
  94. data/lib/avm2/abc/opcodes/function_invocation/as3_callsupervoid.rb +7 -0
  95. data/lib/avm2/abc/opcodes/function_invocation_opcode.rb +17 -0
  96. data/lib/avm2/abc/opcodes/function_return/as3_returnvalue.rb +8 -0
  97. data/lib/avm2/abc/opcodes/function_return/as3_returnvoid.rb +8 -0
  98. data/lib/avm2/abc/opcodes/function_return_opcode.rb +4 -0
  99. data/lib/avm2/abc/opcodes/generic/as3_astypelate.rb +8 -0
  100. data/lib/avm2/abc/opcodes/generic/as3_checkfilter.rb +8 -0
  101. data/lib/avm2/abc/opcodes/generic/as3_dup.rb +8 -0
  102. data/lib/avm2/abc/opcodes/generic/as3_dxnslate.rb +8 -0
  103. data/lib/avm2/abc/opcodes/generic/as3_escxattr.rb +8 -0
  104. data/lib/avm2/abc/opcodes/generic/as3_getglobalscope.rb +8 -0
  105. data/lib/avm2/abc/opcodes/generic/as3_getlex.rb +16 -0
  106. data/lib/avm2/abc/opcodes/generic/as3_getscopeobject.rb +16 -0
  107. data/lib/avm2/abc/opcodes/generic/as3_getslot.rb +16 -0
  108. data/lib/avm2/abc/opcodes/generic/as3_hasnext.rb +8 -0
  109. data/lib/avm2/abc/opcodes/generic/as3_hasnext2.rb +17 -0
  110. data/lib/avm2/abc/opcodes/generic/as3_in.rb +8 -0
  111. data/lib/avm2/abc/opcodes/generic/as3_instanceof.rb +8 -0
  112. data/lib/avm2/abc/opcodes/generic/as3_istypelate.rb +8 -0
  113. data/lib/avm2/abc/opcodes/generic/as3_kill.rb +16 -0
  114. data/lib/avm2/abc/opcodes/generic/as3_label.rb +8 -0
  115. data/lib/avm2/abc/opcodes/generic/as3_nextname.rb +8 -0
  116. data/lib/avm2/abc/opcodes/generic/as3_nextvalue.rb +8 -0
  117. data/lib/avm2/abc/opcodes/generic/as3_nop.rb +8 -0
  118. data/lib/avm2/abc/opcodes/generic/as3_pop.rb +8 -0
  119. data/lib/avm2/abc/opcodes/generic/as3_popscope.rb +8 -0
  120. data/lib/avm2/abc/opcodes/generic/as3_setslot.rb +16 -0
  121. data/lib/avm2/abc/opcodes/generic/as3_swap.rb +8 -0
  122. data/lib/avm2/abc/opcodes/generic/as3_throw.rb +8 -0
  123. data/lib/avm2/abc/opcodes/generic/as3_typeof.rb +8 -0
  124. data/lib/avm2/abc/opcodes/load_store/as3_getlocal.rb +15 -0
  125. data/lib/avm2/abc/opcodes/load_store/as3_getlocal_0.rb +11 -0
  126. data/lib/avm2/abc/opcodes/load_store/as3_getlocal_1.rb +11 -0
  127. data/lib/avm2/abc/opcodes/load_store/as3_getlocal_2.rb +11 -0
  128. data/lib/avm2/abc/opcodes/load_store/as3_getlocal_3.rb +11 -0
  129. data/lib/avm2/abc/opcodes/load_store/as3_setlocal.rb +15 -0
  130. data/lib/avm2/abc/opcodes/load_store/as3_setlocal_0.rb +11 -0
  131. data/lib/avm2/abc/opcodes/load_store/as3_setlocal_1.rb +11 -0
  132. data/lib/avm2/abc/opcodes/load_store/as3_setlocal_2.rb +11 -0
  133. data/lib/avm2/abc/opcodes/load_store/as3_setlocal_3.rb +11 -0
  134. data/lib/avm2/abc/opcodes/load_store_opcode.rb +18 -0
  135. data/lib/avm2/abc/opcodes/object_manipulation/as3_construct.rb +12 -0
  136. data/lib/avm2/abc/opcodes/object_manipulation/as3_constructsuper.rb +16 -0
  137. data/lib/avm2/abc/opcodes/object_manipulation/as3_newactivation.rb +8 -0
  138. data/lib/avm2/abc/opcodes/object_manipulation/as3_newarray.rb +12 -0
  139. data/lib/avm2/abc/opcodes/object_manipulation/as3_newclass.rb +12 -0
  140. data/lib/avm2/abc/opcodes/object_manipulation/as3_newfunction.rb +12 -0
  141. data/lib/avm2/abc/opcodes/object_manipulation/as3_newobject.rb +12 -0
  142. data/lib/avm2/abc/opcodes/object_manipulation_opcode.rb +4 -0
  143. data/lib/avm2/abc/opcodes/opcode.rb +127 -0
  144. data/lib/avm2/abc/opcodes/property/as3_constructprop.rb +20 -0
  145. data/lib/avm2/abc/opcodes/property/as3_deleteproperty.rb +9 -0
  146. data/lib/avm2/abc/opcodes/property/as3_findproperty.rb +9 -0
  147. data/lib/avm2/abc/opcodes/property/as3_findpropstrict.rb +9 -0
  148. data/lib/avm2/abc/opcodes/property/as3_getdescendants.rb +9 -0
  149. data/lib/avm2/abc/opcodes/property/as3_getproperty.rb +9 -0
  150. data/lib/avm2/abc/opcodes/property/as3_getsuper.rb +9 -0
  151. data/lib/avm2/abc/opcodes/property/as3_initproperty.rb +9 -0
  152. data/lib/avm2/abc/opcodes/property/as3_setproperty.rb +9 -0
  153. data/lib/avm2/abc/opcodes/property/as3_setsuper.rb +9 -0
  154. data/lib/avm2/abc/opcodes/property_opcode.rb +13 -0
  155. data/lib/avm2/abc/opcodes/push_literal/as3_pushbyte.rb +11 -0
  156. data/lib/avm2/abc/opcodes/push_literal/as3_pushdouble.rb +11 -0
  157. data/lib/avm2/abc/opcodes/push_literal/as3_pushfalse.rb +7 -0
  158. data/lib/avm2/abc/opcodes/push_literal/as3_pushint.rb +11 -0
  159. data/lib/avm2/abc/opcodes/push_literal/as3_pushnan.rb +7 -0
  160. data/lib/avm2/abc/opcodes/push_literal/as3_pushnull.rb +7 -0
  161. data/lib/avm2/abc/opcodes/push_literal/as3_pushscope.rb +8 -0
  162. data/lib/avm2/abc/opcodes/push_literal/as3_pushshort.rb +11 -0
  163. data/lib/avm2/abc/opcodes/push_literal/as3_pushstring.rb +11 -0
  164. data/lib/avm2/abc/opcodes/push_literal/as3_pushtrue.rb +7 -0
  165. data/lib/avm2/abc/opcodes/push_literal/as3_pushundefined.rb +7 -0
  166. data/lib/avm2/abc/opcodes/push_literal/as3_pushwith.rb +8 -0
  167. data/lib/avm2/abc/opcodes/push_literal_opcode.rb +18 -0
  168. data/lib/avm2/abc/opcodes/type_conversion/as3_applytype.rb +12 -0
  169. data/lib/avm2/abc/opcodes/type_conversion/as3_coerce.rb +16 -0
  170. data/lib/avm2/abc/opcodes/type_conversion/as3_coerce_a.rb +8 -0
  171. data/lib/avm2/abc/opcodes/type_conversion/as3_coerce_b.rb +10 -0
  172. data/lib/avm2/abc/opcodes/type_conversion/as3_coerce_s.rb +10 -0
  173. data/lib/avm2/abc/opcodes/type_conversion/as3_convert_d.rb +10 -0
  174. data/lib/avm2/abc/opcodes/type_conversion/as3_convert_i.rb +10 -0
  175. data/lib/avm2/abc/opcodes/type_conversion/as3_convert_o.rb +10 -0
  176. data/lib/avm2/abc/opcodes/type_conversion/as3_convert_s.rb +10 -0
  177. data/lib/avm2/abc/opcodes/type_conversion/as3_convert_u.rb +10 -0
  178. data/lib/avm2/abc/opcodes/type_conversion_opcode.rb +4 -0
  179. data/lib/avm2/abc/primitives/opcode_sequence.rb +195 -0
  180. data/lib/avm2/abc/primitives/record.rb +132 -0
  181. data/lib/avm2/binary/choice_definition.rb +21 -0
  182. data/lib/avm2/binary/record.rb +469 -0
  183. data/lib/avm2/transform.rb +6 -0
  184. data/lib/avm2/transform/ast_build.rb +206 -0
  185. data/lib/avm2/transform/ast_normalize.rb +0 -0
  186. data/lib/avm2/version.rb +3 -0
  187. data/test/exception.abc +0 -0
  188. data/test/exception.as +29 -0
  189. data/test/literal.abc +0 -0
  190. data/test/literal.as +5 -0
  191. data/test/logic.abc +0 -0
  192. data/test/logic.as +23 -0
  193. data/test/loops.abc +0 -0
  194. data/test/loops.as +30 -0
  195. data/test/number.abc +0 -0
  196. data/test/number.as +14 -0
  197. data/test/switch.abc +0 -0
  198. data/test/switch.as +38 -0
  199. data/test/ternary.abc +0 -0
  200. data/test/ternary.as +22 -0
  201. metadata +579 -0
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ .rbx/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,17 @@
1
+ PATH
2
+ remote: ../furnace
3
+ specs:
4
+ furnace (0.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ trollop (1.16.2)
10
+
11
+ PLATFORMS
12
+ java
13
+ ruby
14
+
15
+ DEPENDENCIES
16
+ furnace!
17
+ trollop
data/abcdump.abc ADDED
Binary file
data/bin/furnace-avm2 ADDED
@@ -0,0 +1,175 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "bundler/setup"
5
+
6
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
7
+
8
+ require "trollop"
9
+ require "avm2"
10
+ require "thread"
11
+ require "benchmark"
12
+
13
+ opts = Trollop::options do
14
+ version "furnace-as3 #{AVM2::VERSION}"
15
+ banner <<-EOS
16
+ furnace-avm2 is a processing tool which operates on ActionScript3 bytecode.
17
+
18
+ Usage: #{__FILE__} [options]
19
+ EOS
20
+
21
+ opt :input, "Input file", :type => :string
22
+ opt :output, "Output file", :type => :string
23
+ opt :verbose, "Be verbose", :default => false
24
+
25
+ opt :only, "Only operate on methods <i+>", :type => :ints, :short => '-O'
26
+ opt :except, "Operate on all methods except <i+>", :type => :ints, :short => '-E'
27
+ opt :grep, "Search <s> in method names", :type => :string, :short => '-G'
28
+
29
+ opt :collect, "Collect failed methods instead of exiting", :default => false
30
+ opt :smallest, "Find method with smallest body", :default => false
31
+
32
+ opt :disasm_before, "Disassemble methods before transforming", :default => false, :short => '-B'
33
+ opt :disasm_after, "Disassemble methods after transforming", :default => false, :short => '-A'
34
+ opt :cfg, "Emit CFG in Graphviz format for methods", :default => false, :short => '-C'
35
+
36
+ opt :dce, "Eliminate dead code", :default => false
37
+ opt :ast, "Build AST", :default => false
38
+ end
39
+
40
+ Trollop::die "Input file is required" unless opts[:input]
41
+ Trollop::die "Stray arguments: #{ARGV}" unless ARGV.empty?
42
+
43
+ abc = nil
44
+ File.open(opts[:input]) do |file|
45
+ abc = AVM2::ABC::File.new
46
+ abc.read(file)
47
+ end
48
+
49
+ disasm = lambda do |body, after|
50
+ puts
51
+ puts "Method #{body.method_idx}," <<
52
+ " max stack #{body.max_stack}, local count #{body.local_count}"
53
+ if after
54
+ puts "After transformation"
55
+ else
56
+ puts "Before transformation"
57
+ end
58
+ puts body.code.disassemble
59
+
60
+ if body.exceptions.any?
61
+ puts
62
+ puts "Exceptions"
63
+ body.exceptions.each do |exception|
64
+ puts " #{exception.from_offset} -> #{exception.to_offset}: " <<
65
+ "catch(#{exception.exc_type} #{exception.var_name}) #{exception.target_offset}"
66
+ end
67
+ end
68
+ end
69
+
70
+ failed = []
71
+ dced = []
72
+ smallest = nil
73
+
74
+ if opts[:grep]
75
+ regexp = Regexp.new(opts[:grep])
76
+
77
+ (abc.klasses + abc.instances).each do |scope|
78
+ if scope.is_a? AVM2::ABC::InstanceInfo
79
+ if scope.name.to_s =~ regexp
80
+ puts "Inst Constructor #{scope.name} #{scope.initializer_idx}"
81
+ end
82
+
83
+ type = "Inst "
84
+ else
85
+ type = "Class"
86
+ end
87
+
88
+ scope.traits.each do |trait|
89
+ if [:Function, :Method].include? trait.kind
90
+ if trait.name.to_s =~ regexp
91
+ puts "#{type} #{trait.kind.to_s.ljust 12} #{trait.name} #{trait.data.method_idx}"
92
+ end
93
+ end
94
+ end
95
+ end
96
+
97
+ exit
98
+ end
99
+
100
+ Thread.abort_on_exception = true
101
+
102
+ threads = []
103
+ bodies = abc.method_bodies.dup
104
+ mutex = Mutex.new
105
+
106
+ 5.times do
107
+ threads << Thread.new do
108
+ loop do
109
+ body = mutex.synchronize { bodies.pop }
110
+ break if body.nil?
111
+
112
+ if (opts[:except] && opts[:except].include?(body.method_idx)) ||
113
+ (opts[:only] && !opts[:only].include?(body.method_idx))
114
+ next
115
+ end
116
+
117
+ begin
118
+ disasm[body, false] if opts[:disasm_before]
119
+
120
+ if opts[:smallest]
121
+ if smallest.nil? || smallest.code_length > body.code_length
122
+ smallest = body
123
+ end
124
+ end
125
+
126
+ if opts[:dce]
127
+ dced << body.method_idx if body.code.eliminate_dead!
128
+ end
129
+
130
+ if opts[:ast]
131
+ ast, = body.build_ast
132
+ puts ast.to_sexp
133
+ end
134
+
135
+ if opts[:cfg]
136
+ cfg = body.code.build_cfg
137
+ File.open("method-#{body.method_idx}.dot", "w") do |dot|
138
+ dot.write cfg.to_graphviz
139
+ end
140
+ end
141
+
142
+ disasm[body, true] if opts[:disasm_after]
143
+ rescue Exception => e
144
+ if opts[:collect]
145
+ #puts "Failure at method body idx=#{body.method_idx}: #{e.class} (#{e.message}) at #{e.backtrace.first}."
146
+ failed << body.method_idx
147
+ else
148
+ raise e
149
+ end
150
+ end
151
+ end
152
+ end
153
+ end
154
+
155
+ threads.each &:join
156
+
157
+ if opts[:verbose]
158
+ if opts[:dce]
159
+ puts "List of methods undergone DCE transform (#{dced.count}):"
160
+ puts " #{dced.join " "}"
161
+ end
162
+ end
163
+
164
+ if opts[:smallest]
165
+ puts "Smallest method is #{smallest.method_idx} with #{smallest.code_length} bytes"
166
+ end
167
+
168
+ if opts[:collect] && failed.any?
169
+ puts "To skip #{failed.count} failed methods, append this command-line argument:"
170
+ puts " --except #{failed.join " "}"
171
+ elsif opts[:output]
172
+ File.open(opts[:output], "w") do |file|
173
+ abc.write(file)
174
+ end
175
+ end
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require "bundler/setup"
5
+
6
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
7
+
8
+ require "avm2"
9
+ require "benchmark"
10
+
11
+ puts "Working on #{RUBY_DESCRIPTION}"
12
+
13
+ Benchmark.bm(7) do |x|
14
+ 5.times do
15
+ abc = nil
16
+
17
+ GC.start
18
+
19
+ x.report("read ") do
20
+ File.open(ARGV.first) do |file|
21
+ abc = AVM2::ABC::File.new
22
+ abc.read(file)
23
+ end
24
+ end
25
+
26
+ x.report("dce ") do
27
+ abc.method_bodies.each do |body|
28
+ body.code.eliminate_dead!
29
+ end
30
+ end
31
+
32
+ x.report("write ") do
33
+ File.open("/dev/null", "w") do |file|
34
+ abc.write(file)
35
+ end
36
+ end
37
+ end
38
+ end
data/darkorbit.abc ADDED
Binary file
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "avm2/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "furnace-avm2"
7
+ s.version = AVM2::VERSION
8
+ s.authors = ["Peter Zotov"]
9
+ s.email = ["whitequark@whitequark.org"]
10
+ s.homepage = "http://github.com/whitequark/furnace-avm2"
11
+ s.summary = %q{AVM2 analysis framework based on Furnace}
12
+ s.description = %q{furnace-avm2 allows one to load, modify and write back} <<
13
+ %q{Flash ActionScript3 bytecode. It can also decompile it.}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_runtime_dependency "furnace"
21
+ s.add_runtime_dependency "trollop"
22
+ end
data/lib/avm2.rb ADDED
@@ -0,0 +1,13 @@
1
+ require "furnace/cfg"
2
+ require "furnace/ast"
3
+ require "furnace/transform"
4
+
5
+ require "furnace/graphviz"
6
+
7
+ module AVM2
8
+ end
9
+
10
+ require "avm2/version"
11
+
12
+ require "avm2/abc"
13
+ require "avm2/transform"
data/lib/avm2/abc.rb ADDED
@@ -0,0 +1,65 @@
1
+ module AVM2::ABC
2
+ AST = Furnace::AST
3
+ CFG = Furnace::CFG
4
+ end
5
+
6
+ require "avm2/binary/choice_definition"
7
+ require "avm2/binary/record"
8
+
9
+ require "avm2/abc/primitives/record"
10
+ require "avm2/abc/primitives/opcode_sequence"
11
+
12
+ require "avm2/abc/opcodes/opcode"
13
+ require "avm2/abc/opcodes/contextual_opcode"
14
+
15
+ require "avm2/abc/opcodes/load_store_opcode"
16
+ require "avm2/abc/opcodes/arithmetic_opcode"
17
+ require "avm2/abc/opcodes/bitwise_opcode"
18
+ require "avm2/abc/opcodes/type_conversion_opcode"
19
+ require "avm2/abc/opcodes/push_literal_opcode"
20
+ require "avm2/abc/opcodes/control_transfer_opcode"
21
+ require "avm2/abc/opcodes/function_invocation_opcode"
22
+ require "avm2/abc/opcodes/function_return_opcode"
23
+ require "avm2/abc/opcodes/exception_opcode"
24
+
25
+ require "avm2/abc/opcodes/property_opcode"
26
+
27
+ Dir[File.join(File.dirname(__FILE__), "abc", "opcodes", "*", "*.rb")].each do |file|
28
+ require file
29
+ end
30
+
31
+ AVM2::ABC::Opcode::MAP.freeze
32
+
33
+ require "avm2/abc/metadata/namespace_info"
34
+ require "avm2/abc/metadata/ns_set_info"
35
+ require "avm2/abc/metadata/multiname_kind_multiname"
36
+ require "avm2/abc/metadata/multiname_kind_multinamel"
37
+ require "avm2/abc/metadata/multiname_kind_qname"
38
+ require "avm2/abc/metadata/multiname_kind_rtqname"
39
+ require "avm2/abc/metadata/multiname_kind_rtqnamel"
40
+ require "avm2/abc/metadata/multiname_kind_genericname"
41
+ require "avm2/abc/metadata/multiname_info"
42
+ require "avm2/abc/metadata/const_pool_info"
43
+
44
+ require "avm2/abc/metadata/option_detail"
45
+ require "avm2/abc/metadata/option_info"
46
+ require "avm2/abc/metadata/method_info"
47
+
48
+ require "avm2/abc/metadata/metadata_info"
49
+
50
+ require "avm2/abc/metadata/trait_slot"
51
+ require "avm2/abc/metadata/trait_method"
52
+ require "avm2/abc/metadata/trait_class"
53
+ require "avm2/abc/metadata/trait_function"
54
+ require "avm2/abc/metadata/trait_info"
55
+ require "avm2/abc/metadata/instance_info"
56
+ require "avm2/abc/metadata/klass_info"
57
+
58
+ require "avm2/abc/metadata/script_info"
59
+
60
+ require "avm2/abc/metadata/exception_info"
61
+ require "avm2/abc/metadata/method_body_info"
62
+
63
+ require "avm2/abc/metadata/file"
64
+
65
+ AVM2::Binary::Record.codegen_each
@@ -0,0 +1,18 @@
1
+ module AVM2::ABC
2
+ class ConstPoolInfo < Record
3
+ def self.cpool_array_of(name, type, options={})
4
+ field_size, field_array = :"#{name}_count", :"#{name}s"
5
+
6
+ vuint30 field_size, :value => lambda { send(field_array).count == 0 ? 0 : send(field_array).count + 1 }
7
+ array field_array, :type => type, :initial_length => lambda { send(field_size) - 1 }, :options => options
8
+ end
9
+
10
+ cpool_array_of :int, :vint32
11
+ cpool_array_of :uint, :vuint32
12
+ cpool_array_of :double, :double
13
+ cpool_array_of :string, :vstring
14
+ cpool_array_of :namespace, :nested, :class => NamespaceInfo
15
+ cpool_array_of :ns_set, :nested, :class => NsSetInfo
16
+ cpool_array_of :multiname, :nested, :class => MultinameInfo
17
+ end
18
+ end
@@ -0,0 +1,29 @@
1
+ module AVM2::ABC
2
+ class ExceptionInfo < Record
3
+ vuint30 :from_offset
4
+ vuint30 :to_offset
5
+ vuint30 :target_offset
6
+ const_ref :exc_type, :string
7
+ const_ref :var_name, :string
8
+
9
+ attr_reader :from, :to, :target
10
+
11
+ def initialize_record(options)
12
+ @parent = options[:parent]
13
+ end
14
+
15
+ def resolve!
16
+ sequence = @parent.code
17
+
18
+ @from = sequence.opcode_at(@from_offset)
19
+ @to = sequence.opcode_at(@to_offset)
20
+ @target = sequence.opcode_at(@target_offset)
21
+ end
22
+
23
+ def lookup!
24
+ @from_offset = @from.offset
25
+ @to_offset = @to.offset
26
+ @target_offset = @target.offset
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,27 @@
1
+ module AVM2::ABC
2
+ class File < Record
3
+ uint16 :minor_version
4
+ uint16 :major_version
5
+
6
+ nested :constant_pool, :class => ConstPoolInfo
7
+
8
+ abc_array_of :method, :nested, :class => MethodInfo
9
+
10
+ abc_array_of :metadata, :nested, :class => MetadataInfo
11
+
12
+ vuint30 :klass_count, :value => lambda { instances.count }
13
+ array :instances, :type => :nested, :initial_length => :klass_count,
14
+ :options => { :class => InstanceInfo }
15
+ array :klasses, :type => :nested, :initial_length => :klass_count,
16
+ :options => { :class => KlassInfo }
17
+ subset :interfaces, :instances, :interface?
18
+
19
+ abc_array_of :script, :nested, :class => ScriptInfo
20
+
21
+ abc_array_of :method_body, :nested, :class => MethodBodyInfo, :plural => :method_bodies
22
+
23
+ def root
24
+ self
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,53 @@
1
+ module AVM2::ABC
2
+ class InstanceInfo < Record
3
+ CLASS_SEALED = 0x01
4
+ CLASS_FINAL = 0x02
5
+ CLASS_INTERFACE = 0x04
6
+ CLASS_PROTECTED_NS = 0x08
7
+
8
+ const_ref :name, :multiname
9
+ const_ref :super_name, :multiname
10
+
11
+ uint8 :flags
12
+ flag :sealed, :flags, CLASS_SEALED
13
+ flag :final, :flags, CLASS_FINAL
14
+ flag :interface, :flags, CLASS_INTERFACE
15
+ flag :protected_ns, :flags, CLASS_PROTECTED_NS
16
+
17
+ const_ref :protected_ns, :namespace, :if => :protected_ns?
18
+
19
+ const_array_of :interface, :multiname
20
+
21
+ root_ref :initializer, :method
22
+
23
+ abc_array_of :trait, :nested, :class => TraitInfo
24
+
25
+ def to_astlet
26
+ if interface?
27
+ root = AST::Node.new(:interface)
28
+ else
29
+ root = AST::Node.new(:instance)
30
+ end
31
+
32
+ root.children << name.to_astlet
33
+
34
+ unless interface?
35
+ if super_name
36
+ root.children << super_name.to_astlet
37
+ else
38
+ root.children << nil
39
+ end
40
+ end
41
+
42
+ if interfaces.any?
43
+ root.children << AST::Node.new(:interfaces, interfaces.map(&:to_astlet))
44
+ end
45
+
46
+ if traits.any?
47
+ root.children << AST::Node.new(:traits, traits.map(&:to_astlet))
48
+ end
49
+
50
+ root.normalize_hierarchy!
51
+ end
52
+ end
53
+ end