furnace-avm2 0.0.9 → 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (126) hide show
  1. data/Gemfile +1 -1
  2. data/Gemfile.lock +4 -3
  3. data/LICENSE +20 -0
  4. data/bin/furnace-avm2 +36 -6
  5. data/bin/furnace-avm2-decompiler +141 -0
  6. data/furnace-avm2.gemspec +2 -2
  7. data/lib/furnace-avm2.rb +1 -0
  8. data/lib/furnace-avm2/abc.rb +24 -7
  9. data/lib/furnace-avm2/abc/metadata/{option_detail.rb → default_value.rb} +5 -1
  10. data/lib/furnace-avm2/abc/metadata/initializer_body.rb +8 -0
  11. data/lib/furnace-avm2/abc/metadata/instance_info.rb +19 -4
  12. data/lib/furnace-avm2/abc/metadata/klass_info.rb +1 -4
  13. data/lib/furnace-avm2/abc/metadata/method_body_info.rb +27 -10
  14. data/lib/furnace-avm2/abc/metadata/method_info.rb +20 -13
  15. data/lib/furnace-avm2/abc/metadata/multiname_info.rb +6 -0
  16. data/lib/furnace-avm2/abc/metadata/multiname_kind_genericname.rb +8 -5
  17. data/lib/furnace-avm2/abc/metadata/multiname_kind_multiname.rb +4 -0
  18. data/lib/furnace-avm2/abc/metadata/multiname_kind_qname.rb +5 -1
  19. data/lib/furnace-avm2/abc/metadata/record_with_value.rb +90 -0
  20. data/lib/furnace-avm2/abc/metadata/script_info.rb +25 -1
  21. data/lib/furnace-avm2/abc/metadata/trait_class.rb +7 -3
  22. data/lib/furnace-avm2/abc/metadata/trait_info.rb +8 -4
  23. data/lib/furnace-avm2/abc/metadata/trait_method.rb +4 -0
  24. data/lib/furnace-avm2/abc/metadata/trait_slot.rb +5 -51
  25. data/lib/furnace-avm2/abc/opcodes/bitwise/as3_lshift.rb +1 -1
  26. data/lib/furnace-avm2/abc/opcodes/bitwise/as3_rshift.rb +1 -1
  27. data/lib/furnace-avm2/abc/opcodes/bitwise/as3_urshift.rb +1 -1
  28. data/lib/furnace-avm2/abc/opcodes/debug/as3_debug.rb +15 -0
  29. data/lib/furnace-avm2/abc/opcodes/debug/as3_debugfile.rb +12 -0
  30. data/lib/furnace-avm2/abc/opcodes/debug/as3_debugline.rb +12 -0
  31. data/lib/furnace-avm2/abc/opcodes/function_invocation/as3_callproplex.rb +21 -0
  32. data/lib/furnace-avm2/abc/opcodes/push_literal/as3_pushbyte.rb +1 -1
  33. data/lib/furnace-avm2/abc/opcodes/push_literal/as3_pushshort.rb +1 -1
  34. data/lib/furnace-avm2/binary/record.rb +21 -1
  35. data/lib/furnace-avm2/source/declaration_tokens/argument_declaration_token.rb +4 -0
  36. data/lib/furnace-avm2/source/declaration_tokens/arguments_token.rb +15 -0
  37. data/lib/furnace-avm2/source/declaration_tokens/callee_token.rb +72 -0
  38. data/lib/furnace-avm2/source/declaration_tokens/class_implementations_token.rb +21 -0
  39. data/lib/furnace-avm2/source/declaration_tokens/class_inheritance_token.rb +17 -0
  40. data/lib/furnace-avm2/source/declaration_tokens/class_name_token.rb +21 -0
  41. data/lib/furnace-avm2/source/declaration_tokens/class_specifiers_token.rb +12 -0
  42. data/lib/furnace-avm2/source/declaration_tokens/class_token.rb +21 -0
  43. data/lib/furnace-avm2/source/declaration_tokens/comment_token.rb +22 -0
  44. data/lib/furnace-avm2/source/declaration_tokens/constructor_specifiers_token.rb +12 -0
  45. data/lib/furnace-avm2/source/declaration_tokens/constructor_token.rb +15 -0
  46. data/lib/furnace-avm2/source/declaration_tokens/function_name_token.rb +14 -0
  47. data/lib/furnace-avm2/source/declaration_tokens/import_token.rb +17 -0
  48. data/lib/furnace-avm2/source/declaration_tokens/initialization_token.rb +7 -0
  49. data/lib/furnace-avm2/source/declaration_tokens/method_specifiers_token.rb +13 -0
  50. data/lib/furnace-avm2/source/declaration_tokens/method_token.rb +15 -0
  51. data/lib/furnace-avm2/source/declaration_tokens/multiname_token.rb +41 -0
  52. data/lib/furnace-avm2/source/declaration_tokens/namespace_name_token.rb +16 -0
  53. data/lib/furnace-avm2/source/declaration_tokens/package_name_token.rb +17 -0
  54. data/lib/furnace-avm2/source/declaration_tokens/package_token.rb +29 -0
  55. data/lib/furnace-avm2/source/declaration_tokens/rest_argument_token.rb +12 -0
  56. data/lib/furnace-avm2/source/declaration_tokens/scope_token.rb +23 -0
  57. data/lib/furnace-avm2/source/declaration_tokens/script_token.rb +14 -0
  58. data/lib/furnace-avm2/source/declaration_tokens/slot_name_token.rb +17 -0
  59. data/lib/furnace-avm2/source/declaration_tokens/slot_token.rb +23 -0
  60. data/lib/furnace-avm2/source/declaration_tokens/specifiers_token.rb +32 -0
  61. data/lib/furnace-avm2/source/declaration_tokens/token_with_traits.rb +51 -0
  62. data/lib/furnace-avm2/source/declaration_tokens/type_token.rb +7 -0
  63. data/lib/furnace-avm2/source/decompiler.rb +669 -0
  64. data/lib/furnace-avm2/source/implementation_tokens/access_token.rb +9 -0
  65. data/lib/furnace-avm2/source/implementation_tokens/array_token.rb +17 -0
  66. data/lib/furnace-avm2/source/implementation_tokens/as_token.rb +9 -0
  67. data/lib/furnace-avm2/source/implementation_tokens/assignment_token.rb +9 -0
  68. data/lib/furnace-avm2/source/implementation_tokens/binary_operator_token.rb +14 -0
  69. data/lib/furnace-avm2/source/implementation_tokens/break_token.rb +9 -0
  70. data/lib/furnace-avm2/source/implementation_tokens/call_token.rb +5 -0
  71. data/lib/furnace-avm2/source/implementation_tokens/continue_token.rb +9 -0
  72. data/lib/furnace-avm2/source/implementation_tokens/control_flow_token.rb +26 -0
  73. data/lib/furnace-avm2/source/implementation_tokens/control_transfer_token.rb +20 -0
  74. data/lib/furnace-avm2/source/implementation_tokens/delete_token.rb +9 -0
  75. data/lib/furnace-avm2/source/implementation_tokens/do_token.rb +9 -0
  76. data/lib/furnace-avm2/source/implementation_tokens/else_if_token.rb +9 -0
  77. data/lib/furnace-avm2/source/implementation_tokens/else_token.rb +22 -0
  78. data/lib/furnace-avm2/source/implementation_tokens/for_each_token.rb +9 -0
  79. data/lib/furnace-avm2/source/implementation_tokens/for_token.rb +9 -0
  80. data/lib/furnace-avm2/source/implementation_tokens/generic_specializers_token.rb +17 -0
  81. data/lib/furnace-avm2/source/implementation_tokens/generic_type_token.rb +9 -0
  82. data/lib/furnace-avm2/source/implementation_tokens/if_token.rb +9 -0
  83. data/lib/furnace-avm2/source/implementation_tokens/immediate_token.rb +14 -0
  84. data/lib/furnace-avm2/source/implementation_tokens/immediate_typename_token.rb +14 -0
  85. data/lib/furnace-avm2/source/implementation_tokens/in_token.rb +9 -0
  86. data/lib/furnace-avm2/source/implementation_tokens/index_token.rb +9 -0
  87. data/lib/furnace-avm2/source/implementation_tokens/is_complex.rb +7 -0
  88. data/lib/furnace-avm2/source/implementation_tokens/is_simple.rb +7 -0
  89. data/lib/furnace-avm2/source/implementation_tokens/is_token.rb +9 -0
  90. data/lib/furnace-avm2/source/implementation_tokens/label_declaration_token.rb +12 -0
  91. data/lib/furnace-avm2/source/implementation_tokens/label_token.rb +12 -0
  92. data/lib/furnace-avm2/source/implementation_tokens/local_variable_token.rb +7 -0
  93. data/lib/furnace-avm2/source/implementation_tokens/new_token.rb +9 -0
  94. data/lib/furnace-avm2/source/implementation_tokens/object_pair_token.rb +9 -0
  95. data/lib/furnace-avm2/source/implementation_tokens/object_token.rb +17 -0
  96. data/lib/furnace-avm2/source/implementation_tokens/parentheses_token.rb +11 -0
  97. data/lib/furnace-avm2/source/implementation_tokens/property_name_token.rb +14 -0
  98. data/lib/furnace-avm2/source/implementation_tokens/return_token.rb +16 -0
  99. data/lib/furnace-avm2/source/implementation_tokens/rtname_token.rb +9 -0
  100. data/lib/furnace-avm2/source/implementation_tokens/statement_token.rb +8 -0
  101. data/lib/furnace-avm2/source/implementation_tokens/super_token.rb +9 -0
  102. data/lib/furnace-avm2/source/implementation_tokens/switch_token.rb +9 -0
  103. data/lib/furnace-avm2/source/implementation_tokens/ternary_operator_token.rb +13 -0
  104. data/lib/furnace-avm2/source/implementation_tokens/throw_token.rb +12 -0
  105. data/lib/furnace-avm2/source/implementation_tokens/typeof_token.rb +13 -0
  106. data/lib/furnace-avm2/source/implementation_tokens/unary_operator_token.rb +14 -0
  107. data/lib/furnace-avm2/source/implementation_tokens/unary_post_operator_token.rb +14 -0
  108. data/lib/furnace-avm2/source/implementation_tokens/variable_name_token.rb +14 -0
  109. data/lib/furnace-avm2/source/implementation_tokens/while_token.rb +9 -0
  110. data/lib/furnace-avm2/transform.rb +5 -1
  111. data/lib/furnace-avm2/transform/ast_build.rb +22 -7
  112. data/lib/furnace-avm2/transform/ast_normalize.rb +61 -20
  113. data/lib/furnace-avm2/transform/cfg_build.rb +86 -0
  114. data/lib/furnace-avm2/transform/cfg_reduce.rb +249 -0
  115. data/lib/furnace-avm2/transform/nf_normalize.rb +130 -0
  116. data/lib/furnace-avm2/version.rb +4 -2
  117. data/test/basic.as +239 -0
  118. metadata +110 -38
  119. data/lib/furnace-avm2/abc/metadata/option_info.rb +0 -5
  120. data/test/exception.as +0 -29
  121. data/test/literal.as +0 -5
  122. data/test/logic.as +0 -23
  123. data/test/loops.as +0 -30
  124. data/test/number.as +0 -14
  125. data/test/switch.as +0 -38
  126. data/test/ternary.as +0 -22
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
1
  source "http://rubygems.org"
2
2
 
3
- gemspec
3
+ gemspec
@@ -1,17 +1,18 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- furnace-avm2 (0.0.8)
5
- furnace (>= 0.0.5)
4
+ furnace-avm2 (0.9.0)
5
+ furnace (>= 0.1.0)
6
6
  trollop
7
7
 
8
8
  GEM
9
9
  remote: http://rubygems.org/
10
10
  specs:
11
- furnace (0.0.5)
11
+ furnace (0.1.0)
12
12
  trollop (1.16.2)
13
13
 
14
14
  PLATFORMS
15
+ java
15
16
  ruby
16
17
 
17
18
  DEPENDENCIES
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Peter Zotov <whitequark@whitequark.org>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a
4
+ copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included
12
+ in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15
+ OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -13,7 +13,7 @@ require "benchmark"
13
13
  include Furnace
14
14
 
15
15
  opts = Trollop::options do
16
- version "furnace-as3 #{AVM2::VERSION}"
16
+ version "furnace-avm2 #{AVM2::VERSION}"
17
17
  banner <<-EOS
18
18
  furnace-avm2 is a processing tool which operates on ActionScript3 bytecode.
19
19
 
@@ -39,6 +39,8 @@ EOS
39
39
 
40
40
  opt :dce, "Eliminate dead code", :default => false
41
41
  opt :ast, "Build AST", :default => false
42
+ opt :nf, "Build NF-AST", :default => false
43
+ opt :decompile, "Decompile methods", :default => false
42
44
  end
43
45
 
44
46
  Trollop::die "Stray arguments: #{ARGV}" unless ARGV.empty?
@@ -50,7 +52,6 @@ File.open(opts[:input]) do |file|
50
52
  end
51
53
 
52
54
  disasm = lambda do |body, after|
53
- puts
54
55
  puts "Method #{body.method_idx}," <<
55
56
  " max stack #{body.max_stack}, local count #{body.local_count}"
56
57
  if after
@@ -68,6 +69,8 @@ disasm = lambda do |body, after|
68
69
  "catch(#{exception.exc_type} #{exception.var_name}) #{exception.target_offset}"
69
70
  end
70
71
  end
72
+
73
+ puts
71
74
  end
72
75
 
73
76
  failed = []
@@ -130,21 +133,48 @@ opts[:threads].times do
130
133
  dced << body.method_idx if body.code.eliminate_dead!
131
134
  end
132
135
 
136
+ disasm[body, true] if opts[:disasm_after]
137
+
133
138
  if opts[:ast]
134
- ast, = body.code_to_ast
135
- puts "Method #{body.method_idx}"
139
+ ast = body.code_to_ast
140
+ puts "Method #{body.method_idx}; AST"
136
141
  puts ast.to_sexp
137
142
  puts
138
143
  end
139
144
 
140
145
  if opts[:cfg]
141
- cfg = body.code.build_cfg
146
+ cfg = body.code_to_cfg
142
147
  File.open("method-#{body.method_idx}.dot", "w") do |dot|
143
148
  dot.write cfg.to_graphviz
144
149
  end
150
+
151
+ puts "Method #{body.method_idx}; dominators"
152
+ cfg.dominators.each do |node, dominating|
153
+ puts "#{node.label.inspect} => " +
154
+ "#{dominating.map(&:label).map(&:inspect).join(", ")}"
155
+ end
156
+ puts
157
+
158
+ puts "Method #{body.method_idx}; loops"
159
+ cfg.identify_loops.each do |header, body|
160
+ puts "#{header.label.inspect} => " +
161
+ "#{body.map(&:label).map(&:inspect).join(", ")}"
162
+ end
163
+ puts
145
164
  end
146
165
 
147
- disasm[body, true] if opts[:disasm_after]
166
+ if opts[:nf]
167
+ ast = body.code_to_nf
168
+ puts "Method #{body.method_idx}; NF-AST"
169
+ puts ast.to_sexp
170
+ puts
171
+ end
172
+
173
+ if opts[:decompile]
174
+ puts "Method #{body.method_idx}"
175
+ puts body.decompile(ns: []).to_text.lstrip
176
+ puts
177
+ end
148
178
  rescue Exception => e
149
179
  if opts[:collect]
150
180
  puts "Failure at method body idx=#{body.method_idx}: #{e.class} (#{e.message}) at #{e.backtrace.first}."
@@ -0,0 +1,141 @@
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 "furnace-avm2"
10
+ require "thread"
11
+
12
+ include Furnace
13
+
14
+ DEBUG_INFO = %w(names funids)
15
+
16
+ opts = Trollop::options do
17
+ version "furnace-avm2 #{AVM2::VERSION} decompiler"
18
+ banner <<-EOS
19
+ furnace-avm2-decompiler is a decompiler for ActionScript3 bytecode.
20
+
21
+ Debugging information classes: #{DEBUG_INFO.join(", ")}.
22
+
23
+ Usage: #{__FILE__} [options]
24
+ EOS
25
+
26
+ opt :input, "Input file", :type => :string, :required => true
27
+ opt :verbose, "Be verbose", :default => false
28
+ opt :debug, "Show debugging information for <s+>.", :type => :strings, :short => '-D'
29
+
30
+ opt :threads, "Use <i> threads for processing", :default => 1
31
+
32
+ opt :only, "Only operate on classes <s+>", :type => :strings, :short => '-O'
33
+ opt :except, "Operate on all classes except <s+>", :type => :strings, :short => '-E'
34
+ opt :grep, "Search <s> (regexp) in class names", :type => :string, :short => '-G'
35
+
36
+ opt :decompile, "Write ActionScript 3 code", :type => :boolean, :short => '-d'
37
+ opt :destructurize, "Write internal token structure", :type => :boolean, :short => '-s'
38
+ end
39
+
40
+ Trollop::die "Stray arguments: #{ARGV}" unless ARGV.empty?
41
+
42
+ decompile_options = {}
43
+
44
+ (opts[:debug] || []).each do |opt|
45
+ Trollop::die "Unknown debug option #{opt}." unless DEBUG_INFO.include? opt
46
+
47
+ decompile_options[:"debug_#{opt}"] = true
48
+ end
49
+
50
+ shound_skip = ->(obj) {
51
+ (opts[:except] && opts[:except].include?(obj.to_s)) ||
52
+ (opts[:only] && !opts[:only].include?(obj.to_s))
53
+ }
54
+
55
+ $stderr.puts "Reading input data..."
56
+
57
+ abc = nil
58
+ File.open(opts[:input]) do |file|
59
+ abc = AVM2::ABC::File.new
60
+ abc.read(file)
61
+ end
62
+
63
+ if opts[:grep]
64
+ regexp = Regexp.new(opts[:grep], Regexp::IGNORECASE)
65
+
66
+ abc.instances.each do |inst|
67
+ if inst.name.to_s =~ regexp
68
+ if inst.interface?
69
+ print "Iface "
70
+ else
71
+ print "Class "
72
+ end
73
+
74
+ print inst.name.to_s.ljust(30)
75
+
76
+ if inst.super_name
77
+ print " extends #{inst.super_name.to_s}"
78
+ end
79
+
80
+ puts
81
+ end
82
+ end
83
+
84
+ exit
85
+ end
86
+
87
+ mutex = Mutex.new
88
+
89
+ roots = {}
90
+ workqueue = abc.instances.dup + abc.scripts.select(&:any_code?)
91
+ total_size = workqueue.size
92
+
93
+ last_percentage = 0
94
+
95
+ $stderr.puts "Decompiling #{total_size} classes and packages..."
96
+
97
+ opts[:threads].times.map do
98
+ Thread.new do
99
+ loop do
100
+ what = nil
101
+ mutex.synchronize do
102
+ 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
+ end
110
+
111
+ break if what.nil?
112
+
113
+ if what.is_a? AVM2::ABC::InstanceInfo
114
+ name = what.name
115
+ ns = name.ns
116
+ else # ScriptInfo
117
+ name = what.traits[0].name.ns
118
+ ns = name.to_s.sub(/(^|\.)[^.]+$/, '')
119
+ end
120
+ next if shound_skip.(name)
121
+
122
+ source = what.decompile(decompile_options)
123
+ next unless source
124
+
125
+ text = source.to_text
126
+
127
+ mutex.synchronize do
128
+ $stderr.print "."
129
+ roots[ns.to_s] ||= []
130
+ roots[ns.to_s] << text
131
+ end
132
+ end
133
+ end
134
+ end.each(&:join)
135
+
136
+ $stderr.puts
137
+
138
+ roots.values.flatten.each do |code|
139
+ puts code
140
+ puts
141
+ end
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
  $:.push File.expand_path("../lib", __FILE__)
3
- require "furnace-avm2"
3
+ require "furnace-avm2/version"
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "furnace-avm2"
@@ -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.0.5'
20
+ s.add_runtime_dependency "furnace", '>= 0.1.0'
21
21
  s.add_runtime_dependency "trollop"
22
22
  end
@@ -1,5 +1,6 @@
1
1
  require "furnace/cfg"
2
2
  require "furnace/ast"
3
+ require "furnace/code"
3
4
  require "furnace/transform"
4
5
 
5
6
  require "furnace/graphviz"
@@ -1,6 +1,6 @@
1
1
  module Furnace::AVM2::ABC
2
- AST = Furnace::AST
3
- CFG = Furnace::CFG
2
+ AST = Furnace::AST
3
+ CFG = Furnace::CFG
4
4
  end
5
5
 
6
6
  require_relative "binary/choice_definition"
@@ -41,11 +41,8 @@ require_relative "abc/metadata/multiname_kind_genericname"
41
41
  require_relative "abc/metadata/multiname_info"
42
42
  require_relative "abc/metadata/const_pool_info"
43
43
 
44
- require_relative "abc/metadata/option_detail"
45
- require_relative "abc/metadata/option_info"
46
- require_relative "abc/metadata/method_info"
47
-
48
- require_relative "abc/metadata/metadata_info"
44
+ require_relative "abc/metadata/record_with_value"
45
+ require_relative "abc/metadata/initializer_body"
49
46
 
50
47
  require_relative "abc/metadata/trait_slot"
51
48
  require_relative "abc/metadata/trait_method"
@@ -53,6 +50,11 @@ require_relative "abc/metadata/trait_class"
53
50
  require_relative "abc/metadata/trait_function"
54
51
  require_relative "abc/metadata/trait_info"
55
52
 
53
+ require_relative "abc/metadata/default_value"
54
+ require_relative "abc/metadata/method_info"
55
+
56
+ require_relative "abc/metadata/metadata_info"
57
+
56
58
  require_relative "abc/metadata/record_with_traits"
57
59
 
58
60
  require_relative "abc/metadata/instance_info"
@@ -66,3 +68,18 @@ require_relative "abc/metadata/method_body_info"
66
68
  require_relative "abc/metadata/file"
67
69
 
68
70
  Furnace::AVM2::Binary::Record.codegen_each
71
+
72
+ require_relative "source/declaration_tokens/token_with_traits"
73
+
74
+ Dir[File.join(File.dirname(__FILE__), "source", "declaration_tokens", "*.rb")].each do |file|
75
+ require file
76
+ end
77
+
78
+ require_relative 'source/implementation_tokens/is_simple'
79
+ require_relative 'source/implementation_tokens/is_complex'
80
+
81
+ Dir[File.join(File.dirname(__FILE__), "source", "implementation_tokens", "*.rb")].each do |file|
82
+ require file
83
+ end
84
+
85
+ require_relative 'source/decompiler'
@@ -1,6 +1,10 @@
1
1
  module Furnace::AVM2::ABC
2
- class OptionDetail < Record
2
+ class DefaultValue < Record
3
+ include RecordWithValue
4
+
3
5
  vuint30 :value_idx
6
+
4
7
  uint8 :value_kind_raw
8
+ xlat_field :value_kind
5
9
  end
6
10
  end
@@ -0,0 +1,8 @@
1
+ module Furnace::AVM2::ABC
2
+ module InitializerBody
3
+ def initializer_body
4
+ root.method_bodies.find { |body| body.method_idx == initializer_idx }
5
+ end
6
+ end
7
+ end
8
+
@@ -1,6 +1,7 @@
1
1
  module Furnace::AVM2::ABC
2
2
  class InstanceInfo < Record
3
3
  include RecordWithTraits
4
+ include InitializerBody
4
5
 
5
6
  CLASS_SEALED = 0x01
6
7
  CLASS_FINAL = 0x02
@@ -28,10 +29,6 @@ module Furnace::AVM2::ABC
28
29
  root.klasses[root.instances.index(self)]
29
30
  end
30
31
 
31
- def initializer_body
32
- root.method_bodies.find { |body| body.method_idx == initializer_idx }
33
- end
34
-
35
32
  def to_astlet
36
33
  if interface?
37
34
  root = AST::Node.new(:interface)
@@ -64,5 +61,23 @@ module Furnace::AVM2::ABC
64
61
 
65
62
  root.normalize_hierarchy!
66
63
  end
64
+
65
+ def collect_ns
66
+ ns = []
67
+ ns << super_name.ns if super_name
68
+ ns += initializer.collect_ns if initializer
69
+ interfaces.each { |iface| ns << iface.ns_set.ns[0] } # stupid avm2
70
+ traits.each { |trait| ns += trait.collect_ns }
71
+ klass.traits.each { |trait| ns += trait.collect_ns }
72
+ ns
73
+ end
74
+
75
+ def decompile(options={})
76
+ Furnace::AVM2::Tokens::PackageToken.new(self,
77
+ options.merge(
78
+ ns: collect_ns,
79
+ package_type: (interface? ? :interface : :class),
80
+ package_name: name))
81
+ end
67
82
  end
68
83
  end
@@ -1,6 +1,7 @@
1
1
  module Furnace::AVM2::ABC
2
2
  class KlassInfo < Record
3
3
  include RecordWithTraits
4
+ include InitializerBody
4
5
 
5
6
  root_ref :initializer, :method
6
7
 
@@ -10,10 +11,6 @@ module Furnace::AVM2::ABC
10
11
  root.instances[root.klasses.index(self)]
11
12
  end
12
13
 
13
- def initializer_body
14
- root.method_bodies.find { |body| body.method_idx == initializer_idx }
15
- end
16
-
17
14
  def to_astlet
18
15
  root = AST::Node.new(:klass)
19
16
 
@@ -19,17 +19,34 @@ module Furnace::AVM2::ABC
19
19
  end
20
20
  end
21
21
 
22
- def code_to_ast
23
- unless @ast
24
- pipeline = Furnace::Transform::Pipeline.new([
25
- Furnace::AVM2::Transform::ASTBuild.new(validate: true),
26
- Furnace::AVM2::Transform::ASTNormalize.new
27
- ])
28
-
29
- @ast, = pipeline.run(code, self)
30
- end
22
+ def code_to_ast(options={})
23
+ pipeline = Furnace::Transform::Pipeline.new([
24
+ Furnace::AVM2::Transform::ASTBuild.new(options),
25
+ Furnace::AVM2::Transform::ASTNormalize.new
26
+ ])
27
+
28
+ pipeline.run(code, self)
29
+ end
30
+
31
+ def code_to_cfg
32
+ pipeline = Furnace::Transform::Pipeline.new([
33
+ Furnace::AVM2::Transform::CFGBuild.new
34
+ ])
35
+
36
+ pipeline.run(*code_to_ast)
37
+ end
38
+
39
+ def code_to_nf
40
+ pipeline = Furnace::Transform::Pipeline.new([
41
+ Furnace::AVM2::Transform::CFGReduce.new,
42
+ Furnace::AVM2::Transform::NFNormalize.new,
43
+ ])
44
+
45
+ pipeline.run(*code_to_cfg)
46
+ end
31
47
 
32
- @ast
48
+ def decompile(options={})
49
+ Furnace::AVM2::Decompiler.new(self, options).decompile
33
50
  end
34
51
  end
35
52
  end