Browse Source

Retab lib

Tab Assassin 6 years ago
parent
commit
7e5e0f7fc8
100 changed files with 46611 additions and 46611 deletions
  1. 2
    2
      lib/anemone/core.rb
  2. 3
    3
      lib/anemone/extractors/anchors.rb
  3. 7
    7
      lib/anemone/extractors/dirbuster.rb
  4. 4
    4
      lib/anemone/extractors/forms.rb
  5. 3
    3
      lib/anemone/extractors/frames.rb
  6. 43
    43
      lib/anemone/extractors/generic.rb
  7. 3
    3
      lib/anemone/extractors/links.rb
  8. 19
    19
      lib/anemone/extractors/meta_refresh.rb
  9. 3
    3
      lib/anemone/extractors/scripts.rb
  10. 4
    4
      lib/anemone/page.rb
  11. 23
    23
      lib/anemone/rex_http.rb
  12. 84
    84
      lib/enumerable.rb
  13. 364
    364
      lib/fastlib.rb
  14. 59
    59
      lib/metasm/metasm.rb
  15. 26
    26
      lib/metasm/metasm/arm/debug.rb
  16. 154
    154
      lib/metasm/metasm/arm/decode.rb
  17. 60
    60
      lib/metasm/metasm/arm/encode.rb
  18. 51
    51
      lib/metasm/metasm/arm/main.rb
  19. 158
    158
      lib/metasm/metasm/arm/opcodes.rb
  20. 115
    115
      lib/metasm/metasm/arm/parse.rb
  21. 40
    40
      lib/metasm/metasm/arm/render.rb
  22. 1423
    1423
      lib/metasm/metasm/compile_c.rb
  23. 172
    172
      lib/metasm/metasm/dalvik/decode.rb
  24. 47
    47
      lib/metasm/metasm/dalvik/main.rb
  25. 296
    296
      lib/metasm/metasm/dalvik/opcodes.rb
  26. 185
    185
      lib/metasm/metasm/decode.rb
  27. 2632
    2632
      lib/metasm/metasm/decompile.rb
  28. 1994
    1994
      lib/metasm/metasm/disassemble.rb
  29. 1253
    1253
      lib/metasm/metasm/disassemble_api.rb
  30. 997
    997
      lib/metasm/metasm/dynldr.rb
  31. 287
    287
      lib/metasm/metasm/encode.rb
  32. 179
    179
      lib/metasm/metasm/exe_format/a_out.rb
  33. 26
    26
      lib/metasm/metasm/exe_format/autoexe.rb
  34. 175
    175
      lib/metasm/metasm/exe_format/bflt.rb
  35. 430
    430
      lib/metasm/metasm/exe_format/coff.rb
  36. 880
    880
      lib/metasm/metasm/exe_format/coff_decode.rb
  37. 1065
    1065
      lib/metasm/metasm/exe_format/coff_encode.rb
  38. 429
    429
      lib/metasm/metasm/exe_format/dex.rb
  39. 120
    120
      lib/metasm/metasm/exe_format/dol.rb
  40. 783
    783
      lib/metasm/metasm/exe_format/elf.rb
  41. 954
    954
      lib/metasm/metasm/exe_format/elf_decode.rb
  42. 1325
    1325
      lib/metasm/metasm/exe_format/elf_encode.rb
  43. 806
    806
      lib/metasm/metasm/exe_format/macho.rb
  44. 205
    205
      lib/metasm/metasm/exe_format/main.rb
  45. 150
    150
      lib/metasm/metasm/exe_format/mz.rb
  46. 156
    156
      lib/metasm/metasm/exe_format/nds.rb
  47. 389
    389
      lib/metasm/metasm/exe_format/pe.rb
  48. 229
    229
      lib/metasm/metasm/exe_format/serialstruct.rb
  49. 101
    101
      lib/metasm/metasm/exe_format/shellcode.rb
  50. 154
    154
      lib/metasm/metasm/exe_format/xcoff.rb
  51. 16
    16
      lib/metasm/metasm/gui.rb
  52. 334
    334
      lib/metasm/metasm/gui/cstruct.rb
  53. 188
    188
      lib/metasm/metasm/gui/dasm_coverage.rb
  54. 329
    329
      lib/metasm/metasm/gui/dasm_decomp.rb
  55. 80
    80
      lib/metasm/metasm/gui/dasm_funcgraph.rb
  56. 1331
    1331
      lib/metasm/metasm/gui/dasm_graph.rb
  57. 532
    532
      lib/metasm/metasm/gui/dasm_hex.rb
  58. 588
    588
      lib/metasm/metasm/gui/dasm_listing.rb
  59. 875
    875
      lib/metasm/metasm/gui/dasm_main.rb
  60. 280
    280
      lib/metasm/metasm/gui/dasm_opcodes.rb
  61. 1197
    1197
      lib/metasm/metasm/gui/debug.rb
  62. 779
    779
      lib/metasm/metasm/gui/gtk.rb
  63. 418
    418
      lib/metasm/metasm/gui/qt.rb
  64. 1631
    1631
      lib/metasm/metasm/gui/win32.rb
  65. 389
    389
      lib/metasm/metasm/gui/x11.rb
  66. 1504
    1504
      lib/metasm/metasm/ia32/compile_c.rb
  67. 181
    181
      lib/metasm/metasm/ia32/debug.rb
  68. 1152
    1152
      lib/metasm/metasm/ia32/decode.rb
  69. 551
    551
      lib/metasm/metasm/ia32/decompile.rb
  70. 301
    301
      lib/metasm/metasm/ia32/encode.rb
  71. 214
    214
      lib/metasm/metasm/ia32/main.rb
  72. 853
    853
      lib/metasm/metasm/ia32/opcodes.rb
  73. 282
    282
      lib/metasm/metasm/ia32/parse.rb
  74. 69
    69
      lib/metasm/metasm/ia32/render.rb
  75. 1090
    1090
      lib/metasm/metasm/main.rb
  76. 240
    240
      lib/metasm/metasm/mips/decode.rb
  77. 34
    34
      lib/metasm/metasm/mips/encode.rb
  78. 51
    51
      lib/metasm/metasm/mips/main.rb
  79. 403
    403
      lib/metasm/metasm/mips/opcodes.rb
  80. 37
    37
      lib/metasm/metasm/mips/parse.rb
  81. 29
    29
      lib/metasm/metasm/mips/render.rb
  82. 11
    11
      lib/metasm/metasm/os/gnu_exports.rb
  83. 1039
    1039
      lib/metasm/metasm/os/linux.rb
  84. 1652
    1652
      lib/metasm/metasm/os/main.rb
  85. 505
    505
      lib/metasm/metasm/os/remote.rb
  86. 1267
    1267
      lib/metasm/metasm/os/windows.rb
  87. 37
    37
      lib/metasm/metasm/os/windows_exports.rb
  88. 842
    842
      lib/metasm/metasm/parse.rb
  89. 3840
    3840
      lib/metasm/metasm/parse_c.rb
  90. 29
    29
      lib/metasm/metasm/pic16c/decode.rb
  91. 5
    5
      lib/metasm/metasm/pic16c/main.rb
  92. 52
    52
      lib/metasm/metasm/pic16c/opcodes.rb
  93. 250
    250
      lib/metasm/metasm/ppc/decode.rb
  94. 239
    239
      lib/metasm/metasm/ppc/decompile.rb
  95. 33
    33
      lib/metasm/metasm/ppc/encode.rb
  96. 115
    115
      lib/metasm/metasm/ppc/main.rb
  97. 381
    381
      lib/metasm/metasm/ppc/opcodes.rb
  98. 37
    37
      lib/metasm/metasm/ppc/parse.rb
  99. 1252
    1252
      lib/metasm/metasm/preprocessor.rb
  100. 0
    0
      lib/metasm/metasm/render.rb

+ 2
- 2
lib/anemone/core.rb View File

@@ -298,10 +298,10 @@ module Anemone
298 298
     #
299 299
     # Kills all active threads
300 300
     #
301
-	def shutdown
301
+  def shutdown
302 302
       @tentacles.each {|t| t.kill rescue nil }
303 303
       @pages = nil
304
-	end
304
+  end
305 305
 
306 306
   end
307 307
 end

+ 3
- 3
lib/anemone/extractors/anchors.rb View File

@@ -1,7 +1,7 @@
1 1
 class Anemone::Extractors::Anchors < Anemone::Extractors::Base
2 2
 
3
-	def run
4
-		doc.search( '//a[@href]' ).map { |a| a['href'] }
5
-	end
3
+  def run
4
+    doc.search( '//a[@href]' ).map { |a| a['href'] }
5
+  end
6 6
 
7 7
 end

+ 7
- 7
lib/anemone/extractors/dirbuster.rb View File

@@ -1,12 +1,12 @@
1 1
 class Anemone::Extractors::Dirbuster < Anemone::Extractors::Base
2 2
 
3
-	def run
4
-		return [] if page.code.to_i != 200
3
+  def run
4
+    return [] if page.code.to_i != 200
5 5
 
6
-		@@dirs ||= nil
6
+    @@dirs ||= nil
7 7
 
8
-		return @@dirs if @@dirs
9
-		@@dirs = IO.read( File.dirname( __FILE__ ) + '/dirbuster/directories' ).split( "\n" )
10
-	end
11
-	
8
+    return @@dirs if @@dirs
9
+    @@dirs = IO.read( File.dirname( __FILE__ ) + '/dirbuster/directories' ).split( "\n" )
10
+  end
11
+  
12 12
 end

+ 4
- 4
lib/anemone/extractors/forms.rb View File

@@ -1,7 +1,7 @@
1 1
 class Anemone::Extractors::Forms < Anemone::Extractors::Base
2 2
 
3
-	def run
4
-		doc.search( '//form[@action]' ).map { |a| a['action'] }
5
-	end
6
-	
3
+  def run
4
+    doc.search( '//form[@action]' ).map { |a| a['action'] }
5
+  end
6
+  
7 7
 end

+ 3
- 3
lib/anemone/extractors/frames.rb View File

@@ -1,7 +1,7 @@
1 1
 class Anemone::Extractors::Frames < Anemone::Extractors::Base
2 2
 
3
-	def run
4
-		doc.css( 'frame', 'iframe' ).map { |a| a.attributes['src'].content rescue next }
5
-	end
3
+  def run
4
+    doc.css( 'frame', 'iframe' ).map { |a| a.attributes['src'].content rescue next }
5
+  end
6 6
 
7 7
 end

+ 43
- 43
lib/anemone/extractors/generic.rb View File

@@ -2,49 +2,49 @@ require 'uri'
2 2
 
3 3
 class Anemone::Extractors::Generic < Anemone::Extractors::Base
4 4
 
5
-	def run
6
-		URI.extract( doc.to_s, %w(http https) ).map do |u|
7
-			#
8
-			# This extractor needs to be a tiny bit intelligent because
9
-			# due to its generic nature it'll inevitably match some garbage.
10
-			#
11
-			# For example, if some JS code contains:
12
-			#
13
-			#	var = 'http://blah.com?id=1'
14
-			#
15
-			# or
16
-			#
17
-			#	var = { 'http://blah.com?id=1', 1 }
18
-			#
19
-			#
20
-			# The URI.extract call will match:
21
-			#
22
-			#	http://blah.com?id=1'
23
-			#
24
-			# and
25
-			#
26
-			#	http://blah.com?id=1',
27
-			#
28
-			# respectively.
29
-			#
30
-			if !includes_quotes?( u )
31
-				u
32
-			else
33
-				if html.include?( "'#{u}" )
34
-					u.split( '\'' ).first
35
-				elsif html.include?( "\"#{u}" )
36
-					u.split( '"' ).first
37
-				else
38
-					u
39
-				end
40
-			end
41
-		end
42
-	rescue
43
-		[]
44
-	end
5
+  def run
6
+    URI.extract( doc.to_s, %w(http https) ).map do |u|
7
+      #
8
+      # This extractor needs to be a tiny bit intelligent because
9
+      # due to its generic nature it'll inevitably match some garbage.
10
+      #
11
+      # For example, if some JS code contains:
12
+      #
13
+      #	var = 'http://blah.com?id=1'
14
+      #
15
+      # or
16
+      #
17
+      #	var = { 'http://blah.com?id=1', 1 }
18
+      #
19
+      #
20
+      # The URI.extract call will match:
21
+      #
22
+      #	http://blah.com?id=1'
23
+      #
24
+      # and
25
+      #
26
+      #	http://blah.com?id=1',
27
+      #
28
+      # respectively.
29
+      #
30
+      if !includes_quotes?( u )
31
+        u
32
+      else
33
+        if html.include?( "'#{u}" )
34
+          u.split( '\'' ).first
35
+        elsif html.include?( "\"#{u}" )
36
+          u.split( '"' ).first
37
+        else
38
+          u
39
+        end
40
+      end
41
+    end
42
+  rescue
43
+    []
44
+  end
45 45
 
46
-	def includes_quotes?( url )
47
-		url.include?( '\'' ) || url.include?( '"' )
48
-	end
46
+  def includes_quotes?( url )
47
+    url.include?( '\'' ) || url.include?( '"' )
48
+  end
49 49
 
50 50
 end

+ 3
- 3
lib/anemone/extractors/links.rb View File

@@ -1,7 +1,7 @@
1 1
 class Anemone::Extractors::Links < Anemone::Extractors::Base
2 2
 
3
-	def run
4
-		doc.search( "//link[@href]" ).map { |a| a['href'] }
5
-	end
3
+  def run
4
+    doc.search( "//link[@href]" ).map { |a| a['href'] }
5
+  end
6 6
 
7 7
 end

+ 19
- 19
lib/anemone/extractors/meta_refresh.rb View File

@@ -1,24 +1,24 @@
1 1
 class Anemone::Extractors::MetaRefresh < Anemone::Extractors::Base
2 2
 
3
-	def run
4
-		doc.search( "//meta[@http-equiv='refresh']" ).map do |url|
5
-			begin
6
-				_, url = url['content'].split( ';', 2 )
7
-				next if !url
8
-				unquote( url.split( '=', 2 ).last )
9
-			rescue
10
-				next
11
-			end
12
-		end
13
-	rescue
14
-		nil
15
-	end
3
+  def run
4
+    doc.search( "//meta[@http-equiv='refresh']" ).map do |url|
5
+      begin
6
+        _, url = url['content'].split( ';', 2 )
7
+        next if !url
8
+        unquote( url.split( '=', 2 ).last )
9
+      rescue
10
+        next
11
+      end
12
+    end
13
+  rescue
14
+    nil
15
+  end
16 16
 
17
-	def unquote( str )
18
-		[ '\'', '"' ].each do |q|
19
-			return str[1...-1] if str.start_with?( q ) && str.end_with?( q )
20
-		end
21
-		str
22
-	end
17
+  def unquote( str )
18
+    [ '\'', '"' ].each do |q|
19
+      return str[1...-1] if str.start_with?( q ) && str.end_with?( q )
20
+    end
21
+    str
22
+  end
23 23
 
24 24
 end

+ 3
- 3
lib/anemone/extractors/scripts.rb View File

@@ -1,7 +1,7 @@
1 1
 class Anemone::Extractors::Scripts < Anemone::Extractors::Base
2 2
 
3
-	def run
4
-		doc.search( '//script[@src]' ).map { |a| a['src'] }
5
-	end
3
+  def run
4
+    doc.search( '//script[@src]' ).map { |a| a['src'] }
5
+  end
6 6
 
7 7
 end

+ 4
- 4
lib/anemone/page.rb View File

@@ -85,8 +85,8 @@ module Anemone
85 85
     def run_extractors
86 86
       return [] if !doc
87 87
       self.class.extractors.map do |e|
88
-	      next if e == Extractors::Dirbuster && !dirbust?
89
-	      e.new( self ).run rescue next
88
+        next if e == Extractors::Dirbuster && !dirbust?
89
+        e.new( self ).run rescue next
90 90
       end.flatten.
91 91
           compact.map do |p|
92 92
               abs = to_absolute( URI( p ) ) rescue next
@@ -186,7 +186,7 @@ module Anemone
186 186
     end
187 187
 
188 188
     def dirbust?
189
-	    @dirbust
189
+      @dirbust
190 190
     end
191 191
 
192 192
     #
@@ -240,7 +240,7 @@ module Anemone
240 240
     end
241 241
 
242 242
     def dup
243
-	  Marshal.load( Marshal.dump( self ) )
243
+    Marshal.load( Marshal.dump( self ) )
244 244
     end
245 245
 
246 246
   end

+ 23
- 23
lib/anemone/rex_http.rb View File

@@ -51,7 +51,7 @@ module Anemone
51 51
           )
52 52
           # Store the associated raw HTTP request
53 53
           page.request = response.request
54
-		  pages << page
54
+      pages << page
55 55
         end
56 56
 
57 57
         return pages
@@ -162,11 +162,11 @@ module Anemone
162 162
         response = nil
163 163
         request  = nil
164 164
         begin
165
-			conn     = connection(url)
166
-			request  = conn.request_raw(opts)
167
-			response = conn.send_recv(request, @opts[:timeout] || 10 )
168
-		rescue ::Errno::EPIPE, ::Timeout::Error
169
-		end
165
+      conn     = connection(url)
166
+      request  = conn.request_raw(opts)
167
+      response = conn.send_recv(request, @opts[:timeout] || 10 )
168
+    rescue ::Errno::EPIPE, ::Timeout::Error
169
+    end
170 170
 
171 171
         finish = Time.now()
172 172
 
@@ -180,28 +180,28 @@ module Anemone
180 180
     end
181 181
 
182 182
     def connection(url)
183
-		context =  { }
184
-		context['Msf']        = @opts[:framework] if @opts[:framework]
185
-		context['MsfExploit'] = @opts[:module] if @opts[:module]
186
-
187
-		conn = Rex::Proto::Http::Client.new(
188
-			url.host,
189
-			url.port.to_i,
190
-			context,
191
-			url.scheme == "https",
192
-			'SSLv23',
193
-			@opts[:proxies],
183
+    context =  { }
184
+    context['Msf']        = @opts[:framework] if @opts[:framework]
185
+    context['MsfExploit'] = @opts[:module] if @opts[:module]
186
+
187
+    conn = Rex::Proto::Http::Client.new(
188
+      url.host,
189
+      url.port.to_i,
190
+      context,
191
+      url.scheme == "https",
192
+      'SSLv23',
193
+      @opts[:proxies],
194 194
                     @opts[:username],
195 195
                     @opts[:password]
196
-		)
196
+    )
197 197
 
198
-		conn.set_config(
199
-			'vhost'      => virtual_host(url),
200
-			'agent'      => user_agent,
198
+    conn.set_config(
199
+      'vhost'      => virtual_host(url),
200
+      'agent'      => user_agent,
201 201
       'domain'     => @opts[:domain]
202
-		)
202
+    )
203 203
 
204
-		conn
204
+    conn
205 205
     end
206 206
 
207 207
     def verbose?

+ 84
- 84
lib/enumerable.rb View File

@@ -18,98 +18,98 @@
18 18
 #
19 19
 module Enumerable
20 20
 
21
-	class << self
22
-		# Provides the cross-product of two or more Enumerables.
23
-		# This is the class-level method. The instance method
24
-		# calls on this.
25
-		#
26
-		#   Enumerable.cart([1,2], [4], ["apple", "banana"])
27
-		#   #=> [[1, 4, "apple"], [1, 4, "banana"], [2, 4, "apple"], [2, 4, "banana"]]
28
-		#
29
-		#   Enumerable.cart([1,2], [3,4])
30
-		#   #=> [[1, 3], [1, 4], [2, 3], [2, 4]]
21
+  class << self
22
+    # Provides the cross-product of two or more Enumerables.
23
+    # This is the class-level method. The instance method
24
+    # calls on this.
25
+    #
26
+    #   Enumerable.cart([1,2], [4], ["apple", "banana"])
27
+    #   #=> [[1, 4, "apple"], [1, 4, "banana"], [2, 4, "apple"], [2, 4, "banana"]]
28
+    #
29
+    #   Enumerable.cart([1,2], [3,4])
30
+    #   #=> [[1, 3], [1, 4], [2, 3], [2, 4]]
31 31
 
32
-		def cartesian_product(*enums, &block)
33
-			result = [[]]
34
-			while [] != enums
35
-				t, result = result, []
36
-				b, *enums = enums
37
-				t.each do |a|
38
-					b.each do |n|
39
-						result << a + [n]
40
-					end
41
-				end
42
-			end
43
-			if block_given?
44
-				result.each{ |e| block.call(e) }
45
-			else
46
-				result
47
-			end
48
-		end
32
+    def cartesian_product(*enums, &block)
33
+      result = [[]]
34
+      while [] != enums
35
+        t, result = result, []
36
+        b, *enums = enums
37
+        t.each do |a|
38
+          b.each do |n|
39
+            result << a + [n]
40
+          end
41
+        end
42
+      end
43
+      if block_given?
44
+        result.each{ |e| block.call(e) }
45
+      else
46
+        result
47
+      end
48
+    end
49 49
 
50
-		alias_method :cart, :cartesian_product
51
-	end
50
+    alias_method :cart, :cartesian_product
51
+  end
52 52
 
53
-	# The instance level version of <tt>Enumerable::cartesian_product</tt>.	
54
-	#
55
-	#   a = []
56
-	#   [1,2].cart([4,5]){|elem| a << elem }
57
-	#   a  #=> [[1, 4],[1, 5],[2, 4],[2, 5]]
53
+  # The instance level version of <tt>Enumerable::cartesian_product</tt>.	
54
+  #
55
+  #   a = []
56
+  #   [1,2].cart([4,5]){|elem| a << elem }
57
+  #   a  #=> [[1, 4],[1, 5],[2, 4],[2, 5]]
58 58
 
59
-	def cartesian_product(*enums, &block)
60
-		Enumerable.cartesian_product(self, *enums, &block)
61
-	end
59
+  def cartesian_product(*enums, &block)
60
+    Enumerable.cartesian_product(self, *enums, &block)
61
+  end
62 62
 
63
-	alias :cart :cartesian_product
63
+  alias :cart :cartesian_product
64 64
 
65
-	# Operator alias for cross-product.
66
-	#
67
-	#   a = [1,2] ** [4,5]
68
-	#   a  #=> [[1, 4],[1, 5],[2, 4],[2, 5]]
69
-	#
70
-	def **(enum)
71
-		Enumerable.cartesian_product(self, enum)
72
-	end
65
+  # Operator alias for cross-product.
66
+  #
67
+  #   a = [1,2] ** [4,5]
68
+  #   a  #=> [[1, 4],[1, 5],[2, 4],[2, 5]]
69
+  #
70
+  def **(enum)
71
+    Enumerable.cartesian_product(self, enum)
72
+  end
73 73
 
74
-	# Expected to be an enumeration of arrays. This method
75
-	# iterates through combinations of each in position.
76
-	#
77
-	#   a = [ [0,1], [2,3] ]
78
-	#   a.each_combo { |c| p c }
79
-	#
80
-	# produces
81
-	#
82
-	#   [0, 2]
83
-	#   [0, 3]
84
-	#   [1, 2]
85
-	#   [1, 3]
86
-	#
87
-	def each_combo
88
-		a = collect{ |x|
89
-			x.respond_to?(:to_a) ? x.to_a : 0..x
90
-		}
74
+  # Expected to be an enumeration of arrays. This method
75
+  # iterates through combinations of each in position.
76
+  #
77
+  #   a = [ [0,1], [2,3] ]
78
+  #   a.each_combo { |c| p c }
79
+  #
80
+  # produces
81
+  #
82
+  #   [0, 2]
83
+  #   [0, 3]
84
+  #   [1, 2]
85
+  #   [1, 3]
86
+  #
87
+  def each_combo
88
+    a = collect{ |x|
89
+      x.respond_to?(:to_a) ? x.to_a : 0..x
90
+    }
91 91
 
92
-		if a.size == 1
93
-			r = a.shift
94
-			r.each{ |n|
95
-				yield n
96
-			}
97
-		else
98
-			r = a.shift
99
-			r.each{ |n|
100
-				a.each_combo{ |s|
101
-					yield [n, *s]
102
-				}
103
-			}
104
-		end
105
-	end
92
+    if a.size == 1
93
+      r = a.shift
94
+      r.each{ |n|
95
+        yield n
96
+      }
97
+    else
98
+      r = a.shift
99
+      r.each{ |n|
100
+        a.each_combo{ |s|
101
+          yield [n, *s]
102
+        }
103
+      }
104
+    end
105
+  end
106 106
 
107
-	# As with each_combo but returns combos collected in an array.
108
-	#
109
-	def combos
110
-		a = []
111
-		each_combo{ |c| a << c }
112
-		a
113
-	end
107
+  # As with each_combo but returns combos collected in an array.
108
+  #
109
+  def combos
110
+    a = []
111
+    each_combo{ |c| a << c }
112
+    a
113
+  end
114 114
 
115 115
 end

+ 364
- 364
lib/fastlib.rb View File

@@ -38,248 +38,248 @@ require "find"
38 38
 #
39 39
 class FastLib
40 40
 
41
-	VERSION = "0.0.8"
42
-
43
-	FLAG_COMPRESS = 0x01
44
-	FLAG_ENCRYPT  = 0x02
45
-
46
-	@@cache = {}
47
-	@@has_zlib = false
48
-
49
-	#
50
-	# Load zlib support if possible
51
-	#
52
-	begin
53
-		require 'zlib'
54
-		@@has_zlib = true
55
-	rescue ::LoadError
56
-	end
57
-
58
-	#
59
-	# This method returns the version of the fastlib library
60
-	#
61
-	def self.version
62
-		VERSION
63
-	end
64
-
65
-	#
66
-	# This method loads content from a specific archive file by name. If the
67
-	# noprocess argument is set to true, the contents will not be expanded to
68
-	# include workarounds for things such as __FILE__. This is useful when
69
-	# loading raw binary data where these strings may occur
70
-	#
71
-	def self.load(lib, name, noprocess=false)
72
-		data = ""
73
-		load_cache(lib)
74
-
75
-		return unless ( @@cache[lib] and @@cache[lib][name] )
76
-
77
-
78
-		::File.open(lib, "rb") do |fd|
79
-			fd.seek(
80
-				@@cache[lib][:fastlib_header][0] +
81
-				@@cache[lib][:fastlib_header][1] +
82
-				@@cache[lib][name][0]
83
-			)
84
-			data = fastlib_filter_decode( lib, fd.read(@@cache[lib][name][1] ))
85
-		end
86
-
87
-		# Return the contents in raw or processed form
88
-		noprocess ? data : post_process(lib, name, data)
89
-	end
90
-
91
-	#
92
-	# This method caches the file list and offsets within the archive
93
-	#
94
-	def self.load_cache(lib)
95
-		return if @@cache[lib]
96
-		@@cache[lib] = {}
97
-
98
-		return if not ::File.exists?(lib)
99
-
100
-		::File.open(lib, 'rb') do |fd|
101
-			dict = {}
102
-			head = fd.read(4)
103
-			return if head != "FAST"
104
-			hlen = fd.read(4).unpack("N")[0]
105
-			flag = fd.read(4).unpack("N")[0]
106
-
107
-			@@cache[lib][:fastlib_header] = [12, hlen, fd.stat.mtime.utc.to_i ]
108
-			@@cache[lib][:fastlib_flags]  = flag
109
-
110
-			nlen, doff, dlen, tims = fd.read(16).unpack("N*")
111
-
112
-			while nlen > 0
113
-				name = fastlib_filter_decode( lib, fd.read(nlen) )
114
-				dict[name] = [doff, dlen, tims]
115
-
116
-				nlen, doff, dlen, tims = fd.read(16).unpack("N*")
117
-			end
118
-
119
-			@@cache[lib].merge!(dict)
120
-		end
121
-
122
-	end
123
-
124
-	#
125
-	# This method provides compression and encryption capabilities
126
-	# for the fastlib archive format.
127
-	#
128
-	def self.fastlib_filter_decode(lib, buff)
129
-
130
-		if (@@cache[lib][:fastlib_flags] & FLAG_ENCRYPT) != 0
131
-
132
-			@@cache[lib][:fastlib_decrypt] ||= ::Proc.new do |data|
133
-				stub = "decrypt_%.8x" % ( @@cache[lib][:fastlib_flags] & 0xfffffff0 )
134
-				FastLib.send(stub, data)
135
-			end
136
-
137
-			buff = @@cache[lib][:fastlib_decrypt].call( buff )
138
-		end
139
-
140
-		if (@@cache[lib][:fastlib_flags] & FLAG_COMPRESS) != 0
141
-			if not @@has_zlib
142
-				raise ::RuntimeError, "zlib is required to open this archive"
143
-			end
144
-
145
-			z = Zlib::Inflate.new
146
-			buff = z.inflate(buff)
147
-			buff << z.finish
148
-			z.close
149
-		end
150
-
151
-		buff
152
-	end
153
-
154
-	#
155
-	# This method provides compression and encryption capabilities
156
-	# for the fastlib archive format.
157
-	#
158
-	def self.fastlib_filter_encode(lib, buff)
159
-
160
-		if (@@cache[lib][:fastlib_flags] & FLAG_COMPRESS) != 0
161
-			if not @@has_zlib
162
-				raise ::RuntimeError, "zlib is required to open this archive"
163
-			end
164
-
165
-			z = Zlib::Deflate.new
166
-			buff = z.deflate(buff)
167
-			buff << z.finish
168
-			z.close
169
-		end
170
-
171
-		if (@@cache[lib][:fastlib_flags] & FLAG_ENCRYPT) != 0
172
-
173
-			@@cache[lib][:fastlib_encrypt] ||= ::Proc.new do |data|
174
-				stub = "encrypt_%.8x" % ( @@cache[lib][:fastlib_flags] & 0xfffffff0 )
175
-				FastLib.send(stub, data)
176
-			end
177
-
178
-			buff = @@cache[lib][:fastlib_encrypt].call( buff )
179
-		end
180
-
181
-		buff
182
-	end
183
-
184
-
185
-	# This method provides a way to create a FASTLIB archive programatically.
186
-	#
187
-	# @param [String] lib the output path for the archive
188
-	# @param [String] flag a string containing the hex values for the
189
-	#   flags ({FLAG_COMPRESS} and {FLAG_ENCRYPT}).
190
-	# @param [String] bdir the path to the base directory which will be
191
-	#   stripped from all paths included in the archive
192
-	# @param [Array<String>] dirs list of directories/files to pack into
193
-	#   the archive.  All dirs should be under bdir so that the paths are
194
-	#   stripped correctly.
195
-	# @return [void]
196
-	def self.dump(lib, flag, bdir, *dirs)
197
-		head = ""
198
-		data = ""
199
-		hidx = 0
200
-		didx = 0
201
-
202
-		bdir = bdir.gsub(/\/$/, '')
203
-		brex = /^#{Regexp.escape(bdir)}\//
204
-
205
-		@@cache[lib] = {
206
-			:fastlib_flags => flag.to_i(16)
207
-		}
208
-
209
-		dirs.each do |dir|
210
-			::Find.find(dir) do |path|
211
-				next if not ::File.file?(path)
212
-				name = fastlib_filter_encode( lib, path.sub( brex, "" ) )
213
-
214
-				buff = ""
215
-				::File.open(path, "rb") do |fd|
216
-					buff = fastlib_filter_encode(lib, fd.read(fd.stat.size))
217
-				end
218
-
219
-
220
-				head << [ name.length, didx, buff.length, ::File.stat(path).mtime.utc.to_i ].pack("NNNN")
221
-				head << name
222
-				hidx = hidx + 16 + name.length
223
-
224
-				data << buff
225
-				didx = didx + buff.length
226
-			end
227
-		end
228
-
229
-		head << [0,0,0].pack("NNN")
230
-
231
-		::File.open(lib, "wb") do |fd|
232
-			fd.write("FAST")
233
-			fd.write( [ head.length, flag.to_i(16) ].pack("NN") )
234
-			fd.write( head )
235
-			fd.write( data )
236
-		end
237
-	end
238
-
239
-	#
240
-	# This archive provides a way to list the contents of an archive
241
-	# file, returning the names only in sorted order.
242
-	#
243
-	def self.list(lib)
244
-		load_cache(lib)
245
-		( @@cache[lib] || {} ).keys.map{|x| x.to_s }.sort.select{ |x| @@cache[lib][x] }
246
-	end
247
-
248
-	#
249
-	# This method is called on the loaded is required to expand __FILE__
250
-	# and other inline dynamic constants to map to the correct location.
251
-	#
252
-	def self.post_process(lib, name, data)
253
-		data.gsub('__FILE__', "'#{ ::File.expand_path(::File.join(::File.dirname(lib), name)) }'")
254
-	end
255
-
256
-	#
257
-	# This is a stub crypto handler that performs a basic XOR
258
-	# operation against a fixed one byte key. The two usable IDs
259
-	# are 12345600 and 00000000
260
-	#
261
-	def self.encrypt_12345600(data)
262
-		encrypt_00000000(data)
263
-	end
264
-
265
-	def self.decrypt_12345600(data)
266
-		encrypt_00000000(data)
267
-	end
268
-
269
-	def self.encrypt_00000000(data)
270
-		data.unpack("C*").map{ |c| c ^ 0x90 }.pack("C*")
271
-	end
272
-
273
-	def self.decrypt_00000000(data)
274
-		encrypt_00000000(data)
275
-	end
276
-
277
-	#
278
-	# Expose the cache to callers
279
-	#
280
-	def self.cache
281
-		@@cache
282
-	end
41
+  VERSION = "0.0.8"
42
+
43
+  FLAG_COMPRESS = 0x01
44
+  FLAG_ENCRYPT  = 0x02
45
+
46
+  @@cache = {}
47
+  @@has_zlib = false
48
+
49
+  #
50
+  # Load zlib support if possible
51
+  #
52
+  begin
53
+    require 'zlib'
54
+    @@has_zlib = true
55
+  rescue ::LoadError
56
+  end
57
+
58
+  #
59
+  # This method returns the version of the fastlib library
60
+  #
61
+  def self.version
62
+    VERSION
63
+  end
64
+
65
+  #
66
+  # This method loads content from a specific archive file by name. If the
67
+  # noprocess argument is set to true, the contents will not be expanded to
68
+  # include workarounds for things such as __FILE__. This is useful when
69
+  # loading raw binary data where these strings may occur
70
+  #
71
+  def self.load(lib, name, noprocess=false)
72
+    data = ""
73
+    load_cache(lib)
74
+
75
+    return unless ( @@cache[lib] and @@cache[lib][name] )
76
+
77
+
78
+    ::File.open(lib, "rb") do |fd|
79
+      fd.seek(
80
+        @@cache[lib][:fastlib_header][0] +
81
+        @@cache[lib][:fastlib_header][1] +
82
+        @@cache[lib][name][0]
83
+      )
84
+      data = fastlib_filter_decode( lib, fd.read(@@cache[lib][name][1] ))
85
+    end
86
+
87
+    # Return the contents in raw or processed form
88
+    noprocess ? data : post_process(lib, name, data)
89
+  end
90
+
91
+  #
92
+  # This method caches the file list and offsets within the archive
93
+  #
94
+  def self.load_cache(lib)
95
+    return if @@cache[lib]
96
+    @@cache[lib] = {}
97
+
98
+    return if not ::File.exists?(lib)
99
+
100
+    ::File.open(lib, 'rb') do |fd|
101
+      dict = {}
102
+      head = fd.read(4)
103
+      return if head != "FAST"
104
+      hlen = fd.read(4).unpack("N")[0]
105
+      flag = fd.read(4).unpack("N")[0]
106
+
107
+      @@cache[lib][:fastlib_header] = [12, hlen, fd.stat.mtime.utc.to_i ]
108
+      @@cache[lib][:fastlib_flags]  = flag
109
+
110
+      nlen, doff, dlen, tims = fd.read(16).unpack("N*")
111
+
112
+      while nlen > 0
113
+        name = fastlib_filter_decode( lib, fd.read(nlen) )
114
+        dict[name] = [doff, dlen, tims]
115
+
116
+        nlen, doff, dlen, tims = fd.read(16).unpack("N*")
117
+      end
118
+
119
+      @@cache[lib].merge!(dict)
120
+    end
121
+
122
+  end
123
+
124
+  #
125
+  # This method provides compression and encryption capabilities
126
+  # for the fastlib archive format.
127
+  #
128
+  def self.fastlib_filter_decode(lib, buff)
129
+
130
+    if (@@cache[lib][:fastlib_flags] & FLAG_ENCRYPT) != 0
131
+
132
+      @@cache[lib][:fastlib_decrypt] ||= ::Proc.new do |data|
133
+        stub = "decrypt_%.8x" % ( @@cache[lib][:fastlib_flags] & 0xfffffff0 )
134
+        FastLib.send(stub, data)
135
+      end
136
+
137
+      buff = @@cache[lib][:fastlib_decrypt].call( buff )
138
+    end
139
+
140
+    if (@@cache[lib][:fastlib_flags] & FLAG_COMPRESS) != 0
141
+      if not @@has_zlib
142
+        raise ::RuntimeError, "zlib is required to open this archive"
143
+      end
144
+
145
+      z = Zlib::Inflate.new
146
+      buff = z.inflate(buff)
147
+      buff << z.finish
148
+      z.close
149
+    end
150
+
151
+    buff
152
+  end
153
+
154
+  #
155
+  # This method provides compression and encryption capabilities
156
+  # for the fastlib archive format.
157
+  #
158
+  def self.fastlib_filter_encode(lib, buff)
159
+
160
+    if (@@cache[lib][:fastlib_flags] & FLAG_COMPRESS) != 0
161
+      if not @@has_zlib
162
+        raise ::RuntimeError, "zlib is required to open this archive"
163
+      end
164
+
165
+      z = Zlib::Deflate.new
166
+      buff = z.deflate(buff)
167
+      buff << z.finish
168
+      z.close
169
+    end
170
+
171
+    if (@@cache[lib][:fastlib_flags] & FLAG_ENCRYPT) != 0
172
+
173
+      @@cache[lib][:fastlib_encrypt] ||= ::Proc.new do |data|
174
+        stub = "encrypt_%.8x" % ( @@cache[lib][:fastlib_flags] & 0xfffffff0 )
175
+        FastLib.send(stub, data)
176
+      end
177
+
178
+      buff = @@cache[lib][:fastlib_encrypt].call( buff )
179
+    end
180
+
181
+    buff
182
+  end
183
+
184
+
185
+  # This method provides a way to create a FASTLIB archive programatically.
186
+  #
187
+  # @param [String] lib the output path for the archive
188
+  # @param [String] flag a string containing the hex values for the
189
+  #   flags ({FLAG_COMPRESS} and {FLAG_ENCRYPT}).
190
+  # @param [String] bdir the path to the base directory which will be
191
+  #   stripped from all paths included in the archive
192
+  # @param [Array<String>] dirs list of directories/files to pack into
193
+  #   the archive.  All dirs should be under bdir so that the paths are
194
+  #   stripped correctly.
195
+  # @return [void]
196
+  def self.dump(lib, flag, bdir, *dirs)
197
+    head = ""
198
+    data = ""
199
+    hidx = 0
200
+    didx = 0
201
+
202
+    bdir = bdir.gsub(/\/$/, '')
203
+    brex = /^#{Regexp.escape(bdir)}\//
204
+
205
+    @@cache[lib] = {
206
+      :fastlib_flags => flag.to_i(16)
207
+    }
208
+
209
+    dirs.each do |dir|
210
+      ::Find.find(dir) do |path|
211
+        next if not ::File.file?(path)
212
+        name = fastlib_filter_encode( lib, path.sub( brex, "" ) )
213
+
214
+        buff = ""
215
+        ::File.open(path, "rb") do |fd|
216
+          buff = fastlib_filter_encode(lib, fd.read(fd.stat.size))
217
+        end
218
+
219
+
220
+        head << [ name.length, didx, buff.length, ::File.stat(path).mtime.utc.to_i ].pack("NNNN")
221
+        head << name
222
+        hidx = hidx + 16 + name.length
223
+
224
+        data << buff
225
+        didx = didx + buff.length
226
+      end
227
+    end
228
+
229
+    head << [0,0,0].pack("NNN")
230
+
231
+    ::File.open(lib, "wb") do |fd|
232
+      fd.write("FAST")
233
+      fd.write( [ head.length, flag.to_i(16) ].pack("NN") )
234
+      fd.write( head )
235
+      fd.write( data )
236
+    end
237
+  end
238
+
239
+  #
240
+  # This archive provides a way to list the contents of an archive
241
+  # file, returning the names only in sorted order.
242
+  #
243
+  def self.list(lib)
244
+    load_cache(lib)
245
+    ( @@cache[lib] || {} ).keys.map{|x| x.to_s }.sort.select{ |x| @@cache[lib][x] }
246
+  end
247
+
248
+  #
249
+  # This method is called on the loaded is required to expand __FILE__
250
+  # and other inline dynamic constants to map to the correct location.
251
+  #
252
+  def self.post_process(lib, name, data)
253
+    data.gsub('__FILE__', "'#{ ::File.expand_path(::File.join(::File.dirname(lib), name)) }'")
254
+  end
255
+
256
+  #
257
+  # This is a stub crypto handler that performs a basic XOR
258
+  # operation against a fixed one byte key. The two usable IDs
259
+  # are 12345600 and 00000000
260
+  #
261
+  def self.encrypt_12345600(data)
262
+    encrypt_00000000(data)
263
+  end
264
+
265
+  def self.decrypt_12345600(data)
266
+    encrypt_00000000(data)
267
+  end
268
+
269
+  def self.encrypt_00000000(data)
270
+    data.unpack("C*").map{ |c| c ^ 0x90 }.pack("C*")
271
+  end
272
+
273
+  def self.decrypt_00000000(data)
274
+    encrypt_00000000(data)
275
+  end
276
+
277
+  #
278
+  # Expose the cache to callers
279
+  #
280
+  def self.cache
281
+    @@cache
282
+  end
283 283
 end
284 284
 
285 285
 
@@ -288,44 +288,44 @@ end
288 288
 # FASTLIB archives
289 289
 #
290 290
 if __FILE__ == $0
291
-	cmd = ARGV.shift
292
-	unless ["store", "list", "version"].include?(cmd)
293
-		$stderr.puts "Usage: #{$0} [dump|list|version] <arguments>"
294
-		exit(0)
295
-	end
296
-
297
-	case cmd
298
-	when "store"
299
-		dst = ARGV.shift
300
-		flg = ARGV.shift
301
-		dir = ARGV.shift
302
-		src = ARGV
303
-		unless dst and dir and src.length > 0
304
-			$stderr.puts "Usage: #{$0} store destination.fastlib flags base_dir src1 src2 ... src99"
305
-			exit(0)
306
-		end
307
-		FastLib.dump(dst, flg, dir, *src)
308
-
309
-	when "list"
310
-		src = ARGV.shift
311
-		unless src
312
-			$stderr.puts "Usage: #{$0} list"
313
-			exit(0)
314
-		end
315
-		$stdout.puts "Library: #{src}"
316
-		$stdout.puts "====================================================="
317
-		FastLib.list(src).each do |name|
318
-			fsize = FastLib.cache[src][name][1]
319
-			ftime = ::Time.at(FastLib.cache[src][name][2]).strftime("%Y-%m-%d %H:%M:%S")
320
-			$stdout.puts sprintf("%9d\t%20s\t%s\n", fsize, ftime, name)
321
-		end
322
-		$stdout.puts ""
323
-
324
-	when "version"
325
-		$stdout.puts "FastLib Version #{FastLib.version}"
326
-	end
327
-
328
-	exit(0)
291
+  cmd = ARGV.shift
292
+  unless ["store", "list", "version"].include?(cmd)
293
+    $stderr.puts "Usage: #{$0} [dump|list|version] <arguments>"
294
+    exit(0)
295
+  end
296
+
297
+  case cmd
298
+  when "store"
299
+    dst = ARGV.shift
300
+    flg = ARGV.shift
301
+    dir = ARGV.shift
302
+    src = ARGV
303
+    unless dst and dir and src.length > 0
304
+      $stderr.puts "Usage: #{$0} store destination.fastlib flags base_dir src1 src2 ... src99"
305
+      exit(0)
306
+    end
307
+    FastLib.dump(dst, flg, dir, *src)
308
+
309
+  when "list"
310
+    src = ARGV.shift
311
+    unless src
312
+      $stderr.puts "Usage: #{$0} list"
313
+      exit(0)
314
+    end
315
+    $stdout.puts "Library: #{src}"
316
+    $stdout.puts "====================================================="
317
+    FastLib.list(src).each do |name|
318
+      fsize = FastLib.cache[src][name][1]
319
+      ftime = ::Time.at(FastLib.cache[src][name][2]).strftime("%Y-%m-%d %H:%M:%S")
320
+      $stdout.puts sprintf("%9d\t%20s\t%s\n", fsize, ftime, name)
321
+    end
322
+    $stdout.puts ""
323
+
324
+  when "version"
325
+    $stdout.puts "FastLib Version #{FastLib.version}"
326
+  end
327
+
328
+  exit(0)
329 329
 end
330 330
 
331 331
 #
@@ -333,95 +333,95 @@ end
333 333
 #
334 334
 =begin
335 335
 
336
-	* All integers are 32-bit and in network byte order (big endian / BE)
337
-	* The file signature is 0x46415354 (big endian, use htonl() if necessary)
338
-	* The header is always 12 bytes into the archive (magic + header length)
339
-	* The data section is always 12 + header length into the archive
340
-	* The header entries always start with 'fastlib_header'
341
-	* The header entries always consist of 16 bytes + name length (no alignment)
342
-	* The header name data may be encoded, compressed, or transformed
343
-	* The data entries may be encoded, compressed, or transformed too
344
-
345
-
346
-	4 bytes: "FAST"
347
-	4 bytes: NBO header length
348
-	4 bytes: NBO flags (24-bit crypto ID, 8 bit modes)
349
-	[
350
-		4 bytes: name length (0 = End of Names)
351
-		4 bytes: data offset
352
-		4 bytes: data length
353
-		4 bytes: timestamp
354
-	]
355
-	[ Raw Data ]
336
+  * All integers are 32-bit and in network byte order (big endian / BE)
337
+  * The file signature is 0x46415354 (big endian, use htonl() if necessary)
338
+  * The header is always 12 bytes into the archive (magic + header length)
339
+  * The data section is always 12 + header length into the archive
340
+  * The header entries always start with 'fastlib_header'
341
+  * The header entries always consist of 16 bytes + name length (no alignment)
342
+  * The header name data may be encoded, compressed, or transformed
343
+  * The data entries may be encoded, compressed, or transformed too
344
+
345
+
346
+  4 bytes: "FAST"
347
+  4 bytes: NBO header length
348
+  4 bytes: NBO flags (24-bit crypto ID, 8 bit modes)
349
+  [
350
+    4 bytes: name length (0 = End of Names)
351
+    4 bytes: data offset
352
+    4 bytes: data length
353
+    4 bytes: timestamp
354
+  ]
355
+  [ Raw Data ]
356 356
 
357 357
 =end
358 358
 
359 359
 
360 360
 module Kernel #:nodoc:all
361
-	alias :fastlib_original_require :require
362
-
363
-	#
364
-	# Store the CWD when were initially loaded
365
-	# required for resolving relative paths
366
-	#
367
-	@@fastlib_base_cwd = ::Dir.pwd
368
-
369
-	#
370
-	# This method hooks the original Kernel.require to support
371
-	# loading files within FASTLIB archives
372
-	#
373
-	def require(name)
374
-		fastlib_require(name) || fastlib_original_require(name)
375
-	end
376
-
377
-	#
378
-	# This method handles the loading of FASTLIB archives
379
-	#
380
-	def fastlib_require(name)
381
-		name = name + ".rb" if not name =~ /\.rb$/
382
-		return false if fastlib_already_loaded?(name)
383
-		return false if fastlib_already_tried?(name)
384
-
385
-		# XXX Implement relative search paths within archives
386
-		$:.map{ |path|
387
-			(path =~ /^([A-Za-z]\:|\/)/ ) ? path : ::File.expand_path( ::File.join(@@fastlib_base_cwd, path) )
388
-		}.map{  |path| ::Dir["#{path}/*.fastlib"] }.flatten.uniq.each do |lib|
389
-			data = FastLib.load(lib, name)
390
-			next if not data
391
-			$" << name
392
-
393
-			Object.class_eval(data, lib + "::" + name)
394
-
395
-			return true
396
-		end
397
-
398
-		$fastlib_miss << name
399
-
400
-		false
401
-	end
402
-
403
-	#
404
-	# This method determines whether the specific file name
405
-	# has already been loaded ($LOADED_FEATURES aka $")
406
-	#
407
-	def fastlib_already_loaded?(name)
408
-		re = Regexp.new("^" + Regexp.escape(name) + "$")
409
-		$".detect { |e| e =~ re } != nil
410
-	end
411
-
412
-	#
413
-	# This method determines whether the specific file name
414
-	# has already been attempted with the included FASTLIB
415
-	# archives.
416
-	#
417
-	# TODO: Ensure that this only applies to known FASTLIB
418
-	#       archives and that newly included archives will
419
-	#       be searched appropriately.
420
-	#
421
-	def fastlib_already_tried?(name)
422
-		$fastlib_miss ||= []
423
-		$fastlib_miss.include?(name)
424
-	end
361
+  alias :fastlib_original_require :require
362
+
363
+  #
364
+  # Store the CWD when were initially loaded
365
+  # required for resolving relative paths
366
+  #
367
+  @@fastlib_base_cwd = ::Dir.pwd
368
+
369
+  #
370
+  # This method hooks the original Kernel.require to support
371
+  # loading files within FASTLIB archives
372
+  #
373
+  def require(name)
374
+    fastlib_require(name) || fastlib_original_require(name)
375
+  end
376
+
377
+  #
378
+  # This method handles the loading of FASTLIB archives
379
+  #
380
+  def fastlib_require(name)
381
+    name = name + ".rb" if not name =~ /\.rb$/
382
+    return false if fastlib_already_loaded?(name)
383
+    return false if fastlib_already_tried?(name)
384
+
385
+    # XXX Implement relative search paths within archives
386
+    $:.map{ |path|
387
+      (path =~ /^([A-Za-z]\:|\/)/ ) ? path : ::File.expand_path( ::File.join(@@fastlib_base_cwd, path) )
388
+    }.map{  |path| ::Dir["#{path}/*.fastlib"] }.flatten.uniq.each do |lib|
389
+      data = FastLib.load(lib, name)
390
+      next if not data
391
+      $" << name
392
+
393
+      Object.class_eval(data, lib + "::" + name)
394
+
395
+      return true
396
+    end
397
+
398
+    $fastlib_miss << name
399
+
400
+    false
401
+  end
402
+
403
+  #
404
+  # This method determines whether the specific file name
405
+  # has already been loaded ($LOADED_FEATURES aka $")
406
+  #
407
+  def fastlib_already_loaded?(name)
408
+    re = Regexp.new("^" + Regexp.escape(name) + "$")
409
+    $".detect { |e| e =~ re } != nil
410
+  end
411
+
412
+  #
413
+  # This method determines whether the specific file name
414
+  # has already been attempted with the included FASTLIB
415
+  # archives.
416
+  #
417
+  # TODO: Ensure that this only applies to known FASTLIB
418
+  #       archives and that newly included archives will
419
+  #       be searched appropriately.
420
+  #
421
+  def fastlib_already_tried?(name)
422
+    $fastlib_miss ||= []
423
+    $fastlib_miss.include?(name)
424
+  end
425 425
 end
426 426
 
427 427
 

+ 59
- 59
lib/metasm/metasm.rb View File

@@ -5,76 +5,76 @@
5 5
 
6 6
 
7 7
 module Metasm
8
-	# root directory for metasm files
9
-	# used by some scripts, eg to find samples/dasm-plugin directory
10
-	Metasmdir = File.dirname(__FILE__)
11
-	# add it to the ruby library path
12
-	$: << Metasmdir
8
+  # root directory for metasm files
9
+  # used by some scripts, eg to find samples/dasm-plugin directory
10
+  Metasmdir = File.dirname(__FILE__)
11
+  # add it to the ruby library path
12
+  $: << Metasmdir
13 13
 
14
-	# constants defined in the same file as another
15
-	Const_autorequire_equiv = {
16
-		'X86' => 'Ia32', 'PPC' => 'PowerPC',
17
-		'X64' => 'X86_64', 'AMD64' => 'X86_64',
18
-		'UniversalBinary' => 'MachO', 'COFFArchive' => 'COFF',
19
-		'DEY' => 'DEX',
20
-		'PTrace' => 'LinOS', 'FatELF' => 'ELF',
21
-		'LoadedELF' => 'ELF', 'LoadedPE' => 'PE',
22
-		'LoadedAutoExe' => 'AutoExe',
23
-		'LinuxRemoteString' => 'LinOS',
24
-		'LinDebugger' => 'LinOS',
25
-		'WinAPI' => 'WinOS',
26
-		'WindowsRemoteString' => 'WinOS', 'WinDbgAPI' => 'WinOS',
27
-		'WinDebugger' => 'WinOS',
28
-		'GdbRemoteString' => 'GdbClient', 'GdbRemoteDebugger' => 'GdbClient',
29
-		'DecodedInstruction' => 'Disassembler', 'DecodedFunction' => 'Disassembler',
30
-		'InstructionBlock' => 'Disassembler',
31
-	}
14
+  # constants defined in the same file as another
15
+  Const_autorequire_equiv = {
16
+    'X86' => 'Ia32', 'PPC' => 'PowerPC',
17
+    'X64' => 'X86_64', 'AMD64' => 'X86_64',
18
+    'UniversalBinary' => 'MachO', 'COFFArchive' => 'COFF',
19
+    'DEY' => 'DEX',
20
+    'PTrace' => 'LinOS', 'FatELF' => 'ELF',
21
+    'LoadedELF' => 'ELF', 'LoadedPE' => 'PE',
22
+    'LoadedAutoExe' => 'AutoExe',
23
+    'LinuxRemoteString' => 'LinOS',
24
+    'LinDebugger' => 'LinOS',
25
+    'WinAPI' => 'WinOS',
26
+    'WindowsRemoteString' => 'WinOS', 'WinDbgAPI' => 'WinOS',
27
+    'WinDebugger' => 'WinOS',
28
+    'GdbRemoteString' => 'GdbClient', 'GdbRemoteDebugger' => 'GdbClient',
29
+    'DecodedInstruction' => 'Disassembler', 'DecodedFunction' => 'Disassembler',
30
+    'InstructionBlock' => 'Disassembler',
31
+  }
32 32
 
33
-	# files to require to get the definition of those constants
34
-	Const_autorequire = {
35
-		'Ia32' => 'ia32', 'MIPS' => 'mips', 'PowerPC' => 'ppc', 'ARM' => 'arm',
36
-		'X86_64' => 'x86_64', 'Sh4' => 'sh4', 'Dalvik' => 'dalvik',
37
-		'C' => 'compile_c',
38
-		'MZ' => 'exe_format/mz', 'PE' => 'exe_format/pe',
39
-		'ELF' => 'exe_format/elf', 'COFF' => 'exe_format/coff',
40
-		'Shellcode' => 'exe_format/shellcode', 'AutoExe' => 'exe_format/autoexe',
41
-		'AOut' => 'exe_format/a_out', 'MachO' => 'exe_format/macho',
42
-		'DEX' => 'exe_format/dex',
43
-		'NDS' => 'exe_format/nds', 'XCoff' => 'exe_format/xcoff',
44
-		'Bflt' => 'exe_format/bflt', 'Dol' => 'exe_format/dol',
45
-		'Gui' => 'gui',
46
-		'WindowsExports' => 'os/windows_exports',
47
-		'GNUExports' => 'os/gnu_exports',
48
-		'LinOS' => 'os/linux', 'WinOS' => 'os/windows',
49
-		'GdbClient' => 'os/remote',
50
-		'Disassembler' => 'disassemble',
51
-		'Decompiler' => 'decompile',
52
-		'DynLdr' => 'dynldr',
53
-	}
33
+  # files to require to get the definition of those constants
34
+  Const_autorequire = {
35
+    'Ia32' => 'ia32', 'MIPS' => 'mips', 'PowerPC' => 'ppc', 'ARM' => 'arm',
36
+    'X86_64' => 'x86_64', 'Sh4' => 'sh4', 'Dalvik' => 'dalvik',
37
+    'C' => 'compile_c',
38
+    'MZ' => 'exe_format/mz', 'PE' => 'exe_format/pe',
39
+    'ELF' => 'exe_format/elf', 'COFF' => 'exe_format/coff',
40
+    'Shellcode' => 'exe_format/shellcode', 'AutoExe' => 'exe_format/autoexe',
41
+    'AOut' => 'exe_format/a_out', 'MachO' => 'exe_format/macho',
42
+    'DEX' => 'exe_format/dex',
43
+    'NDS' => 'exe_format/nds', 'XCoff' => 'exe_format/xcoff',
44
+    'Bflt' => 'exe_format/bflt', 'Dol' => 'exe_format/dol',
45
+    'Gui' => 'gui',
46
+    'WindowsExports' => 'os/windows_exports',
47
+    'GNUExports' => 'os/gnu_exports',
48
+    'LinOS' => 'os/linux', 'WinOS' => 'os/windows',
49
+    'GdbClient' => 'os/remote',
50
+    'Disassembler' => 'disassemble',
51
+    'Decompiler' => 'decompile',
52
+    'DynLdr' => 'dynldr',
53
+  }
54 54
 
55
-	# use the Module.autoload ruby functionnality to load framework components on demand
56
-	Const_autorequire.each { |cst, file|
57
-		autoload cst, File.join('metasm', file)
58
-	}
55
+  # use the Module.autoload ruby functionnality to load framework components on demand
56
+  Const_autorequire.each { |cst, file|
57
+    autoload cst, File.join('metasm', file)
58
+  }
59 59
 
60
-	Const_autorequire_equiv.each { |cst, eqv|
61
-		file = Const_autorequire[eqv]
62
-		autoload cst, File.join('metasm', file)
63
-	}
60
+  Const_autorequire_equiv.each { |cst, eqv|
61
+    file = Const_autorequire[eqv]
62
+    autoload cst, File.join('metasm', file)
63
+  }
64 64
 end
65 65
 
66 66
 # load Metasm core files
67 67
 %w[main encode decode render exe_format/main os/main].each { |f|
68
-	require File.join('metasm', f)
68
+  require File.join('metasm', f)
69 69
 }
70 70
 
71 71
 
72 72
 # remove an 1.9 warning, couldn't find a compatible way...
73 73
 if Hash.new.respond_to?(:key)
74
-	puts "using ruby1.9 workaround for Hash#index warning" if $DEBUG
75
-	class Hash
76
-		alias index_premetasm index rescue nil
77
-		undef index rescue nil
78
-		alias index key
79
-	end
74
+  puts "using ruby1.9 workaround for Hash#index warning" if $DEBUG
75
+  class Hash
76
+    alias index_premetasm index rescue nil
77
+    undef index rescue nil
78
+    alias index key
79
+  end
80 80
 end

+ 26
- 26
lib/metasm/metasm/arm/debug.rb View File

@@ -8,32 +8,32 @@ require 'metasm/arm/opcodes'
8 8
 
9 9
 module Metasm
10 10
 class ARM
11
-	def dbg_register_pc
12
-		@dbg_register_pc ||= :pc
13
-	end
14
-	def dbg_register_flags
15
-		@dbg_register_flags ||= :flags
16
-	end
17
-
18
-	def dbg_register_list 
19
-		@dbg_register_list ||= [:r0, :r1, :r2, :r3, :r4, :r5, :r6, :r7, :r8, :r9, :r10, :r11, :r12, :sp, :lr, :pc]
20
-	end
21
-
22
-	def dbg_flag_list
23
-		@dbg_flag_list ||= []
24
-	end
25
-
26
-	def dbg_register_size
27
-		@dbg_register_size ||= Hash.new(32)
28
-	end
29
-
30
-	def dbg_need_stepover(dbg, addr, di)
31
-		di and di.opcode.props[:saveip]
32
-	end
33
-
34
-	def dbg_end_stepout(dbg, addr, di)
35
-		di and di.opcode.name == 'foobar'	# TODO
36
-	end
11
+  def dbg_register_pc
12
+    @dbg_register_pc ||= :pc
13
+  end
14
+  def dbg_register_flags
15
+    @dbg_register_flags ||= :flags
16
+  end
17
+
18
+  def dbg_register_list 
19
+    @dbg_register_list ||= [:r0, :r1, :r2, :r3, :r4, :r5, :r6, :r7, :r8, :r9, :r10, :r11, :r12, :sp, :lr, :pc]
20
+  end
21
+
22
+  def dbg_flag_list
23
+    @dbg_flag_list ||= []
24
+  end
25
+
26
+  def dbg_register_size
27
+    @dbg_register_size ||= Hash.new(32)
28
+  end
29
+
30
+  def dbg_need_stepover(dbg, addr, di)
31
+    di and di.opcode.props[:saveip]
32
+  end
33
+
34
+  def dbg_end_stepout(dbg, addr, di)
35
+    di and di.opcode.name == 'foobar'	# TODO
36
+  end
37 37
 
38 38
 end
39 39
 end

+ 154
- 154
lib/metasm/metasm/arm/decode.rb View File

@@ -8,160 +8,160 @@ require 'metasm/decode'
8 8
 
9 9
 module Metasm
10 10
 class ARM
11
-	# create the bin_mask for a given opcode
12
-	def build_opcode_bin_mask(op)
13
-		# bit = 0 if can be mutated by an field value, 1 if fixed by opcode
14
-		op.bin_mask = 0
15
-		op.fields.each { |k, (m, s)|
16
-			op.bin_mask |= m << s
17
-		}
18
-		op.bin_mask = 0xffffffff ^ op.bin_mask
19
-	end
20
-
21
-	# create the lookaside hash from the first byte of the opcode
22
-	def build_bin_lookaside
23
-		lookaside = Array.new(256) { [] }
24
-
25
-		opcode_list.each { |op|
26
-			build_opcode_bin_mask op
27
-
28
-			b   = (op.bin >> 20) & 0xff
29
-			msk = (op.bin_mask >> 20) & 0xff
30
-			b &= msk
31
-
32
-			for i in b..(b | (255^msk))
33
-				lookaside[i] << op if i & msk == b
34
-			end
35
-		}
36
-
37
-		lookaside
38
-	end
39
-
40
-	def decode_findopcode(edata)
41
-		return if edata.ptr >= edata.data.length
42
-		di = DecodedInstruction.new(self)
43
-		val = edata.decode_imm(:u32, @endianness)
44
-		di.instance_variable_set('@raw', val)
45
-		di if di.opcode = @bin_lookaside[(val >> 20) & 0xff].find { |op|
46
-			(not op.props[:cond] or
47
-			 ((val >> @fields_shift[:cond]) & @fields_mask[:cond]) != 0xf) and
48
-			(op.bin & op.bin_mask) == (val & op.bin_mask)
49
-		}
50
-	end
51
-
52
-	def disassembler_default_func
53
-		df = DecodedFunction.new
54
-		df
55
-	end
56
-
57
-	def decode_instr_op(edata, di)
58
-		op = di.opcode
59
-		di.instruction.opname = op.name
60
-		val = di.instance_variable_get('@raw')
61
-		
62
-		field_val = lambda { |f|
63
-			r = (val >> @fields_shift[f]) & @fields_mask[f]
64
-			case f
65
-			when :i16; Expression.make_signed(r, 16)
66
-			when :i24; Expression.make_signed(r, 24)
67
-			when :i8_12; ((r >> 4) & 0xf0) | (r & 0xf)
68
-			when :stype; [:lsl, :lsr, :asr, :ror][r]
69
-			when :u; [:-, :+][r]
70
-			else r
71
-			end
72
-		}
73
-
74
-		if op.props[:cond]
75
-			cd = %w[eq ne cs cc mi pl vs vc hi ls ge lt gt le al][field_val[:cond]]
76
-			if cd != 'al'
77
-				di.opcode = di.opcode.dup
78
-				di.instruction.opname = di.opcode.name.dup
79
-				di.instruction.opname[(op.props[:cond_name_off] || di.opcode.name.length), 0] = cd
80
-				if di.opcode.props[:stopexec]
81
-					di.opcode.props = di.opcode.props.dup
82
-					di.opcode.props.delete :stopexec
83
-				end
84
-			end
85
-		end
86
-
87
-		op.args.each { |a|
88
-			di.instruction.args << case a
89
-			when :rd, :rn, :rm; Reg.new field_val[a]
90
-			when :rm_rs; Reg.new field_val[:rm], field_val[:stype], Reg.new(field_val[:rs])
91
-			when :rm_is; Reg.new field_val[:rm], field_val[:stype], field_val[:shifti]*2
92
-			when :i24; Expression[field_val[a] << 2]
93
-			when :i8_r
94
-				i = field_val[:i8]
95
-				r = field_val[:rotate]*2
96
-				Expression[((i >> r) | (i << (32-r))) & 0xffff_ffff]
97
-			when :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12
98
-				b = Reg.new(field_val[:rn])
99
-				o = case a
100
-				when :mem_rn_rm; Reg.new(field_val[:rm])
101
-				when :mem_rn_i8_12; field_val[:i8_12]
102
-				when :mem_rn_rms; Reg.new(field_val[:rm], field_val[:stype], field_val[:shifti]*2)
103
-				when :mem_rn_i12; field_val[:i12]
104
-				end
105
-				Memref.new(b, o, field_val[:u], op.props[:baseincr])
106
-			when :reglist
107
-				di.instruction.args.last.updated = true if op.props[:baseincr]
108
-				msk = field_val[a]
109
-				l = RegList.new((0..15).map { |i| Reg.new(i) if (msk & (1 << i)) > 0 }.compact)
110
-				l.usermoderegs = true if op.props[:usermoderegs]
111
-				l
112
-			else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
113
-			end
114
-		}
115
-
116
-		di.bin_length = 4
117
-		di
118
-	end
119
-
120
-	def decode_instr_interpret(di, addr)
121
-		if di.opcode.args.include? :i24
122
-			di.instruction.args[-1] = Expression[di.instruction.args[-1] + addr + 8]
123
-		end
124
-		di
125
-	end
126
-
127
-	def backtrace_binding
128
-		@backtrace_binding ||= init_backtrace_binding
129
-	end
11
+  # create the bin_mask for a given opcode
12
+  def build_opcode_bin_mask(op)
13
+    # bit = 0 if can be mutated by an field value, 1 if fixed by opcode
14
+    op.bin_mask = 0
15
+    op.fields.each { |k, (m, s)|
16
+      op.bin_mask |= m << s
17
+    }
18
+    op.bin_mask = 0xffffffff ^ op.bin_mask
19
+  end
20
+
21
+  # create the lookaside hash from the first byte of the opcode
22
+  def build_bin_lookaside
23
+    lookaside = Array.new(256) { [] }
24
+
25
+    opcode_list.each { |op|
26
+      build_opcode_bin_mask op
27
+
28
+      b   = (op.bin >> 20) & 0xff
29
+      msk = (op.bin_mask >> 20) & 0xff
30
+      b &= msk
31
+
32
+      for i in b..(b | (255^msk))
33
+        lookaside[i] << op if i & msk == b
34
+      end
35
+    }
36
+
37
+    lookaside
38
+  end
39
+
40
+  def decode_findopcode(edata)
41
+    return if edata.ptr >= edata.data.length
42
+    di = DecodedInstruction.new(self)
43
+    val = edata.decode_imm(:u32, @endianness)
44
+    di.instance_variable_set('@raw', val)
45
+    di if di.opcode = @bin_lookaside[(val >> 20) & 0xff].find { |op|
46
+      (not op.props[:cond] or
47
+       ((val >> @fields_shift[:cond]) & @fields_mask[:cond]) != 0xf) and
48
+      (op.bin & op.bin_mask) == (val & op.bin_mask)
49
+    }
50
+  end
51
+
52
+  def disassembler_default_func
53
+    df = DecodedFunction.new
54
+    df
55
+  end
56
+
57
+  def decode_instr_op(edata, di)
58
+    op = di.opcode
59
+    di.instruction.opname = op.name
60
+    val = di.instance_variable_get('@raw')
61
+    
62
+    field_val = lambda { |f|
63
+      r = (val >> @fields_shift[f]) & @fields_mask[f]
64
+      case f
65
+      when :i16; Expression.make_signed(r, 16)
66
+      when :i24; Expression.make_signed(r, 24)
67
+      when :i8_12; ((r >> 4) & 0xf0) | (r & 0xf)
68
+      when :stype; [:lsl, :lsr, :asr, :ror][r]
69
+      when :u; [:-, :+][r]
70
+      else r
71
+      end
72
+    }
73
+
74
+    if op.props[:cond]
75
+      cd = %w[eq ne cs cc mi pl vs vc hi ls ge lt gt le al][field_val[:cond]]
76
+      if cd != 'al'
77
+        di.opcode = di.opcode.dup
78
+        di.instruction.opname = di.opcode.name.dup
79
+        di.instruction.opname[(op.props[:cond_name_off] || di.opcode.name.length), 0] = cd
80
+        if di.opcode.props[:stopexec]
81
+          di.opcode.props = di.opcode.props.dup
82
+          di.opcode.props.delete :stopexec
83
+        end
84
+      end
85
+    end
86
+
87
+    op.args.each { |a|
88
+      di.instruction.args << case a
89
+      when :rd, :rn, :rm; Reg.new field_val[a]
90
+      when :rm_rs; Reg.new field_val[:rm], field_val[:stype], Reg.new(field_val[:rs])
91
+      when :rm_is; Reg.new field_val[:rm], field_val[:stype], field_val[:shifti]*2
92
+      when :i24; Expression[field_val[a] << 2]
93
+      when :i8_r
94
+        i = field_val[:i8]
95
+        r = field_val[:rotate]*2
96
+        Expression[((i >> r) | (i << (32-r))) & 0xffff_ffff]
97
+      when :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12
98
+        b = Reg.new(field_val[:rn])
99
+        o = case a
100
+        when :mem_rn_rm; Reg.new(field_val[:rm])
101
+        when :mem_rn_i8_12; field_val[:i8_12]
102
+        when :mem_rn_rms; Reg.new(field_val[:rm], field_val[:stype], field_val[:shifti]*2)
103
+        when :mem_rn_i12; field_val[:i12]
104
+        end
105
+        Memref.new(b, o, field_val[:u], op.props[:baseincr])
106
+      when :reglist
107
+        di.instruction.args.last.updated = true if op.props[:baseincr]
108
+        msk = field_val[a]
109
+        l = RegList.new((0..15).map { |i| Reg.new(i) if (msk & (1 << i)) > 0 }.compact)
110
+        l.usermoderegs = true if op.props[:usermoderegs]
111
+        l
112
+      else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
113
+      end
114
+    }
115
+
116
+    di.bin_length = 4
117
+    di
118
+  end
119
+
120
+  def decode_instr_interpret(di, addr)
121
+    if di.opcode.args.include? :i24
122
+      di.instruction.args[-1] = Expression[di.instruction.args[-1] + addr + 8]
123
+    end
124
+    di
125
+  end
126
+
127
+  def backtrace_binding
128
+    @backtrace_binding ||= init_backtrace_binding
129
+  end
130 130
  
131
-	def init_backtrace_binding
132
-		@backtrace_binding ||= {}
133
-	end
134
-
135
-	def get_backtrace_binding(di)
136
-		a = di.instruction.args.map { |arg|
137
-			case arg
138
-			when Reg; arg.symbolic
139
-			when Memref; arg.symbolic(di.address)
140
-			else arg
141
-			end
142
-		}
143
-	
144
-		if binding = backtrace_binding[di.opcode.name]
145
-			bd = binding[di, *a]
146
-		else
147
-			puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
148
-			# assume nothing except the 1st arg is modified
149
-			case a[0]
150
-			when Indirection, Symbol; { a[0] => Expression::Unknown }
151
-			when Expression; (x = a[0].externals.first) ? { x => Expression::Unknown } : {}
152
-			else {}
153
-			end.update(:incomplete_binding => Expression[1])
154
-		end
155
-
156
-	end
157
-	
158
-	def get_xrefs_x(dasm, di)
159
-		if di.opcode.props[:setip]
160
-			[di.instruction.args.last]
161
-		else
162
-			# TODO ldr pc, ..
163
-			[]
164
-		end
165
-	end
131
+  def init_backtrace_binding
132
+    @backtrace_binding ||= {}
133
+  end
134
+
135
+  def get_backtrace_binding(di)
136
+    a = di.instruction.args.map { |arg|
137
+      case arg
138
+      when Reg; arg.symbolic
139
+      when Memref; arg.symbolic(di.address)
140
+      else arg
141
+      end
142
+    }
143
+  
144
+    if binding = backtrace_binding[di.opcode.name]
145
+      bd = binding[di, *a]
146
+    else
147
+      puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
148
+      # assume nothing except the 1st arg is modified
149
+      case a[0]
150
+      when Indirection, Symbol; { a[0] => Expression::Unknown }
151
+      when Expression; (x = a[0].externals.first) ? { x => Expression::Unknown } : {}
152
+      else {}
153
+      end.update(:incomplete_binding => Expression[1])
154
+    end
155
+
156
+  end
157
+  
158
+  def get_xrefs_x(dasm, di)
159
+    if di.opcode.props[:setip]
160
+      [di.instruction.args.last]
161
+    else
162
+      # TODO ldr pc, ..
163
+      []
164
+    end
165
+  end
166 166
 end
167 167
 end

+ 60
- 60
lib/metasm/metasm/arm/encode.rb View File

@@ -9,69 +9,69 @@ require 'metasm/encode'
9 9
 
10 10
 module Metasm
11 11
 class ARM
12
-	def encode_instr_op(section, instr, op)
13
-		base = op.bin
14
-		set_field = lambda { |f, v|
15
-			v = v.reduce if v.kind_of? Expression
16
-			case f
17
-			when :i8_12
18
-				base = Expression[base, :|, [[v, :&, 0xf], :|, [[v, :<<, 4], :&, 0xf00]]]
19
-				next
20
-			when :stype; v = [:lsl, :lsr, :asr, :ror].index(v)
21
-			when :u; v = [:-, :+].index(v)
22
-			end
23
-			base = Expression[base, :|, [[v, :&, @fields_mask[f]], :<<, @fields_shift[f]]]
24
-		}
12
+  def encode_instr_op(section, instr, op)
13
+    base = op.bin
14
+    set_field = lambda { |f, v|
15
+      v = v.reduce if v.kind_of? Expression
16
+      case f
17
+      when :i8_12
18
+        base = Expression[base, :|, [[v, :&, 0xf], :|, [[v, :<<, 4], :&, 0xf00]]]
19
+        next
20
+      when :stype; v = [:lsl, :lsr, :asr, :ror].index(v)
21
+      when :u; v = [:-, :+].index(v)
22
+      end
23
+      base = Expression[base, :|, [[v, :&, @fields_mask[f]], :<<, @fields_shift[f]]]
24
+    }
25 25
 
26
-		val, mask, shift = 0, 0, 0
26
+    val, mask, shift = 0, 0, 0
27 27
 
28
-		if op.props[:cond]
29
-			coff = op.props[:cond_name_off] || op.name.length
30
-			cd = instr.opname[coff, 2]
31
-			cdi = %w[eq ne cs cc mi pl vs vc hi ls ge lt gt le al].index(cd) || 14	# default = al
32
-			set_field[:cond, cdi]
33
-		end
28
+    if op.props[:cond]
29
+      coff = op.props[:cond_name_off] || op.name.length
30
+      cd = instr.opname[coff, 2]
31
+      cdi = %w[eq ne cs cc mi pl vs vc hi ls ge lt gt le al].index(cd) || 14	# default = al
32
+      set_field[:cond, cdi]
33
+    end
34 34
 
35
-		op.args.zip(instr.args).each { |sym, arg|
36
-			case sym
37
-			when :rd, :rs, :rn, :rm; set_field[sym, arg.i]
38
-			when :rm_rs
39
-				set_field[:rm, arg.i]
40
-				set_field[:stype, arg.stype]
41
-				set_field[:rs, arg.shift.i]
42
-			when :rm_is
43
-				set_field[:rm, arg.i]
44
-				set_field[:stype, arg.stype]
45
-				set_field[:shifti, arg.shift/2]
46
-			when :mem_rn_rm, :mem_rn_rms, :mem_rn_i8_12, :mem_rn_i12
47
-				set_field[:rn, arg.base.i]
48
-				case sym
49
-				when :mem_rn_rm
50
-					set_field[:rm, arg.offset.i]
51
-				when :mem_rn_rms
52
-					set_field[:rm, arg.offset.i]
53
-					set_field[:stype, arg.offset.stype]
54
-					set_field[:rs, arg.offset.shift.i]
55
-				when :mem_rn_i8_12
56
-					set_field[:i8_12, arg.offset]
57
-				when :mem_rn_i12
58
-					set_field[:i12, arg.offset]
59
-				end
60
-				# TODO set_field[:u] etc
61
-			when :reglist
62
-				set_field[sym, arg.list.inject(0) { |rl, r| rl | (1 << r.i) }]
63
-			when :i8_r
64
-				# XXX doublecheck this
65
-				b = arg.reduce & 0xffffffff
66
-				r = (0..15).find { next true if b < 0x10 ; b = (b >> 2) | ((b & 3) << 30) }
67
-				set_field[:i8, b]
68
-				set_field[:rotate, r]
69
-			when :i16, :i24
70
-				val, mask, shift = arg, @fields_mask[sym], @fields_shift[sym]
71
-			end
72
-		}
35
+    op.args.zip(instr.args).each { |sym, arg|
36
+      case sym
37
+      when :rd, :rs, :rn, :rm; set_field[sym, arg.i]
38
+      when :rm_rs
39
+        set_field[:rm, arg.i]
40
+        set_field[:stype, arg.stype]
41
+        set_field[:rs, arg.shift.i]
42
+      when :rm_is
43
+        set_field[:rm, arg.i]
44
+        set_field[:stype, arg.stype]
45
+        set_field[:shifti, arg.shift/2]
46
+      when :mem_rn_rm, :mem_rn_rms, :mem_rn_i8_12, :mem_rn_i12
47
+        set_field[:rn, arg.base.i]
48
+        case sym
49
+        when :mem_rn_rm
50
+          set_field[:rm, arg.offset.i]
51
+        when :mem_rn_rms
52
+          set_field[:rm, arg.offset.i]
53
+          set_field[:stype, arg.offset.stype]
54
+          set_field[:rs, arg.offset.shift.i]
55
+        when :mem_rn_i8_12
56
+          set_field[:i8_12, arg.offset]
57
+        when :mem_rn_i12
58
+          set_field[:i12, arg.offset]
59
+        end
60
+        # TODO set_field[:u] etc
61
+      when :reglist
62
+        set_field[sym, arg.list.inject(0) { |rl, r| rl | (1 << r.i) }]
63
+      when :i8_r
64
+        # XXX doublecheck this
65
+        b = arg.reduce & 0xffffffff
66
+        r = (0..15).find { next true if b < 0x10 ; b = (b >> 2) | ((b & 3) << 30) }
67
+        set_field[:i8, b]
68
+        set_field[:rotate, r]
69
+      when :i16, :i24
70
+        val, mask, shift = arg, @fields_mask[sym], @fields_shift[sym]
71
+      end
72
+    }
73 73
 
74
-		Expression[base, :|, [[val, :<<, shift], :&, mask]].encode(:u32, @endianness)
75
-	end
74
+    Expression[base, :|, [[val, :<<, shift], :&, mask]].encode(:u32, @endianness)
75
+  end
76 76
 end
77 77
 end

+ 51
- 51
lib/metasm/metasm/arm/main.rb View File

@@ -8,65 +8,65 @@ require 'metasm/main'
8 8
 
9 9
 module Metasm
10 10
 class ARM < CPU
11
-	class Reg
12
-		class << self
13
-			attr_accessor :s_to_i, :i_to_s
14
-		end
15
-		@i_to_s = %w[r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc]
16
-		@s_to_i = { 'wr' => 7, 'sb' => 9, 'sl' => 10, 'fp' => 11, 'ip' => 12, 'sp' => 13, 'lr' => 14, 'pc' => 15 }
17
-		15.times { |i| @s_to_i["r#{i}"] = i }
18
-		4.times { |i| @s_to_i["a#{i+1}"] = i }
19
-		8.times { |i| @s_to_i["v#{i+1}"] = i+4 }
11
+  class Reg
12
+    class << self
13
+      attr_accessor :s_to_i, :i_to_s
14
+    end
15
+    @i_to_s = %w[r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc]
16
+    @s_to_i = { 'wr' => 7, 'sb' => 9, 'sl' => 10, 'fp' => 11, 'ip' => 12, 'sp' => 13, 'lr' => 14, 'pc' => 15 }
17
+    15.times { |i| @s_to_i["r#{i}"] = i }
18
+    4.times { |i| @s_to_i["a#{i+1}"] = i }
19
+    8.times { |i| @s_to_i["v#{i+1}"] = i+4 }
20 20
 
21
-		attr_accessor :i, :stype, :shift, :updated
22
-		def initialize(i, stype=:lsl, shift=0)
23
-			@i = i
24
-			@stype = stype
25
-			@shift = shift
26
-		end
21
+    attr_accessor :i, :stype, :shift, :updated
22
+    def initialize(i, stype=:lsl, shift=0)
23
+      @i = i
24
+      @stype = stype
25
+      @shift = shift
26
+    end
27 27
 
28
-		def symbolic
29
-			r = self.class.i_to_s[@i].to_sym
30
-			if @stype == :lsl and @shift == 0
31
-				r
32
-			else
33
-				r	# TODO shift/rotate/...
34
-			end
35
-		end
36
-	end
28
+    def symbolic
29
+      r = self.class.i_to_s[@i].to_sym
30
+      if @stype == :lsl and @shift == 0
31
+        r
32
+      else
33
+        r	# TODO shift/rotate/...
34
+      end
35
+    end
36
+  end
37 37
 
38
-	class Memref
39
-		attr_accessor :base, :offset, :sign, :incr
40
-		def initialize(base, offset, sign=:+, incr=nil)
41
-			@base, @offset, @sign, @incr = base, offset, sign, incr
42
-		end
38
+  class Memref
39
+    attr_accessor :base, :offset, :sign, :incr
40
+    def initialize(base, offset, sign=:+, incr=nil)
41
+      @base, @offset, @sign, @incr = base, offset, sign, incr
42
+    end
43 43
 
44
-		def symbolic(len=4, orig=nil)
45
-			o = @offset
46
-			o = o.symbolic if o.kind_of? Reg
47
-			p = Expression[@base.symbolic, @sign, o].reduce
48
-			Indirection[p, len, orig]
49
-		end
50
-	end
44
+    def symbolic(len=4, orig=nil)
45
+      o = @offset
46
+      o = o.symbolic if o.kind_of? Reg
47
+      p = Expression[@base.symbolic, @sign, o].reduce
48
+      Indirection[p, len, orig]
49
+    end
50
+  end
51 51
 
52
-	class RegList
53
-		attr_accessor :list, :usermoderegs
52
+  class RegList
53
+    attr_accessor :list, :usermoderegs
54 54
 
55
-		def initialize(l=[])
56
-			@list = l
57
-		end
58
-	end
55
+    def initialize(l=[])
56
+      @list = l
57
+    end
58
+  end
59 59
 
60
-	def initialize(endianness = :little)
61
-		super()
62
-		@endianness = endianness
63
-		@size = 32
64
-	end
60
+  def initialize(endianness = :little)
61
+    super()
62
+    @endianness = endianness
63
+    @size = 32
64
+  end
65 65
 
66
-	def init_opcode_list
67
-		init_latest
68
-		@opcode_list
69
-	end
66
+  def init_opcode_list
67
+    init_latest
68
+    @opcode_list
69
+  end
70 70
 end
71 71
 
72 72
 class ARM_THUMB < ARM

+ 158
- 158
lib/metasm/metasm/arm/opcodes.rb View File

@@ -8,170 +8,170 @@ require 'metasm/arm/main'
8 8
 
9 9
 module Metasm
10 10
 class ARM
11
-	private
12
-	def addop(name, bin, *args)
13
-		args << :cond if not args.delete :uncond
14
-
15
-		o = Opcode.new name, bin
16
-		o.args.concat(args & @valid_args)
17
-		(args & @valid_props).each { |p| o.props[p] = true }
18
-		args.grep(Hash).each { |h| o.props.update h }
19
-
20
-		# special args -> multiple fields
21
-		case (o.args & [:i8_r, :rm_is, :rm_rs, :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12]).first
22
-		when :i8_r; args << :i8 << :rotate
23
-		when :rm_is; args << :rm << :stype << :shifti
24
-		when :rm_rs; args << :rm << :stype << :rs
25
-		when :mem_rn_rm; args << :rn << :rm << :rsx << :u
26
-		when :mem_rn_i8_12; args << :rn << :i8_12 << :u
27
-		when :mem_rn_rms; args << :rn << :rm << :stype << :shifti << :u
28
-		when :mem_rn_i12; args << :rn << :i12 << :u
29
-		end
30
-
31
-		(args & @fields_mask.keys).each { |f|
32
-			o.fields[f] = [@fields_mask[f], @fields_shift[f]]
33
-		}
34
-
35
-		@opcode_list << o
36
-	end
37
-
38
-	def addop_data_s(name, op, a1, a2, *h)
39
-		addop name, op | (1 << 25), a1, a2, :i8_r, :rotate, *h
40
-		addop name, op, a1, a2, :rm_is, *h
41
-		addop name, op | (1 << 4), a1, a2, :rm_rs, *h
42
-	end
43
-	def addop_data(name, op, a1, a2)
44
-		addop_data_s name, op << 21, a1, a2
45
-		addop_data_s name+'s', (op << 21) | (1 << 20), a1, a2, :cond_name_off => name.length
46
-	end
47
-
48
-	def addop_load_puw(name, op, *a)
49
-		addop name, op, {:baseincr => :post}, :rd, :u, *a
50
-		addop name, op | (1 << 24), :rd, :u, *a
51
-		addop name, op | (1 << 24) | (1 << 21), {:baseincr => :pre}, :rd, :u, *a
52
-	end
53
-	def addop_load_lsh_o(name, op)
54
-		addop_load_puw name, op, :rsz, :mem_rn_rm, {:cond_name_off => 3}
55
-		addop_load_puw name, op | (1 << 22), :mem_rn_i8_12, {:cond_name_off => 3}
56
-	end
57
-	def addop_load_lsh
58
-		op = 9 << 4
59
-		addop_load_lsh_o 'strh',  op | (1 << 5)
60
-		addop_load_lsh_o 'ldrd',  op | (1 << 6)
61
-		addop_load_lsh_o 'strd',  op | (1 << 6) | (1 << 5)
62
-		addop_load_lsh_o 'ldrh',  op | (1 << 20) | (1 << 5)
63
-		addop_load_lsh_o 'ldrsb', op | (1 << 20) | (1 << 6)
64
-		addop_load_lsh_o 'ldrsh', op | (1 << 20) | (1 << 6) | (1 << 5)
65
-	end
66
-
67
-	def addop_load_puwt(name, op, *a)
68
-		addop_load_puw name, op, *a
69
-		addop name+'t', op | (1 << 21), {:baseincr => :post, :cond_name_off => name.length}, :rd, :u, *a
70
-	end
71
-	def addop_load_o(name, op, *a)
72
-		addop_load_puwt name, op, :mem_rn_i12, *a
73
-		addop_load_puwt name, op | (1 << 25), :mem_rn_rms, *a
74
-	end
75
-	def addop_load(name, op)
76
-		addop_load_o name, op
77
-		addop_load_o name+'b', op | (1 << 22), :cond_name_off => name.length
78
-	end
79
-
80
-	def addop_ldm_go(name, op, *a)
81
-		addop name, op, :rn, :reglist, {:cond_name_off => 3}, *a
82
-	end
83
-	def addop_ldm_w(name, op, *a)
84
-		addop_ldm_go name, op, *a		# base reg untouched
85
-		addop_ldm_go name, op | (1 << 21), {:baseincr => :post}, *a	# base updated
86
-	end
87
-	def addop_ldm_s(name, op)
88
-		addop_ldm_w name, op			# transfer regs
89
-		addop_ldm_w name, op | (1 << 22), :usermoderegs	# transfer usermode regs
90
-	end
91
-	def addop_ldm_p(name, op)
92
-		addop_ldm_s name+'a', op		# target memory included
93
-		addop_ldm_s name+'b', op | (1 << 24)	# target memory excluded, transfer starts at next addr
94
-	end
95
-	def addop_ldm_u(name, op)
96
-		addop_ldm_p name+'d', op		# transfer made downward
97
-		addop_ldm_p name+'i', op | (1 << 23)	# transfer made upward
98
-	end
99
-	def addop_ldm(name, op)
100
-		addop_ldm_u name, op
101
-	end
102
-
103
-	# ARMv6 instruction set, aka arm7/arm9
104
-	def init_arm_v6
105
-		@opcode_list = []
106
-		@valid_props << :baseincr << :cond << :cond_name_off << :usermoderegs <<
107
-				:tothumb << :tojazelle
108
-		@valid_args.concat [:rn, :rd, :rm, :crn, :crd, :crm, :cpn, :reglist, :i24,
109
-			:rm_rs, :rm_is, :i8_r, :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12]
110
-		@fields_mask.update :rn => 0xf, :rd => 0xf, :rs => 0xf, :rm => 0xf,
111
-			:crn => 0xf, :crd => 0xf, :crm => 0xf, :cpn => 0xf,
112
-			:rnx => 0xf, :rdx => 0xf, :rsx => 0xf,
113
-			:shifti => 0x1f, :stype => 3, :rotate => 0xf, :reglist => 0xffff,
114
-			:i8 => 0xff, :i12 => 0xfff, :i24 => 0xff_ffff, :i8_12 => 0xf0f,
115
-			:u => 1, :mask => 0xf, :sbo => 0xf, :cond => 0xf
116
-
117
-		@fields_shift.update :rn => 16, :rd => 12, :rs => 8, :rm => 0,
118
-			:crn => 16, :crd => 12, :crm => 0, :cpn => 8,
119
-			:rnx => 16, :rdx => 12, :rsx => 8,
120
-			:shifti => 7, :stype => 5, :rotate => 8, :reglist => 0,
121
-			:i8 => 0, :i12 => 0, :i24 => 0, :i8_12 => 0,
122
-			:u => 23, :mask => 16, :sbo => 12, :cond => 28
123
-		
124
-		addop_data 'and', 0,  :rd, :rn
125
-		addop_data 'eor', 1,  :rd, :rn
126
-		addop_data 'xor', 1,  :rd, :rn
127
-		addop_data 'sub', 2,  :rd, :rn
128
-		addop_data 'rsb', 3,  :rd, :rn
129
-		addop_data 'add', 4,  :rd, :rn
130
-		addop_data 'adc', 5,  :rd, :rn
131
-		addop_data 'sbc', 6,  :rd, :rn
132
-		addop_data 'rsc', 7,  :rd, :rn
133
-		addop_data 'tst', 8,  :rdx, :rn
134
-		addop_data 'teq', 9,  :rdx, :rn
135
-		addop_data 'cmp', 10, :rdx, :rn
136
-		addop_data 'cmn', 11, :rdx, :rn
137
-		addop_data 'orr', 12, :rd, :rn
138
-		addop_data 'or',  12, :rd, :rn
139
-		addop_data 'mov', 13, :rd, :rnx
140
-		addop_data 'bic', 14, :rd, :rn
141
-		addop_data 'mvn', 15, :rd, :rnx
142
-		
143
-		addop 'b',  0b1010 << 24, :setip, :stopexec, :i24
144
-		addop 'bl', 0b1011 << 24, :setip, :stopexec, :i24, :saveip
145
-		addop 'bkpt', (0b00010010 << 20) | (0b0111 << 4)		# other fields are available&unused, also cnd != AL is undef
146
-		addop 'blx', 0b1111101 << 25, :setip, :stopexec, :saveip, :tothumb, :h, :nocond, :i24
147
-		addop 'blx', (0b00010010 << 20) | (0b0011 << 4), :setip, :stopexec, :saveip, :tothumb, :rm
148
-		addop 'bx',  (0b00010010 << 20) | (0b0001 << 4), :setip, :stopexec, :rm
149
-		addop 'bxj',  (0b00010010 << 20) | (0b0010 << 4), :setip, :stopexec, :rm, :tojazelle
150
-
151
-		addop_load 'str', (1 << 26)
152
-		addop_load 'ldr', (1 << 26) | (1 << 20)
153
-		addop_load_lsh
154
-		addop_ldm 'stm', (1 << 27)
155
-		addop_ldm 'ldm', (1 << 27) | (1 << 20)
156
-	end
157
-	alias init_latest init_arm_v6
11
+  private
12
+  def addop(name, bin, *args)
13
+    args << :cond if not args.delete :uncond
14
+
15
+    o = Opcode.new name, bin
16
+    o.args.concat(args & @valid_args)
17
+    (args & @valid_props).each { |p| o.props[p] = true }
18
+    args.grep(Hash).each { |h| o.props.update h }
19
+
20
+    # special args -> multiple fields
21
+    case (o.args & [:i8_r, :rm_is, :rm_rs, :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12]).first
22
+    when :i8_r; args << :i8 << :rotate
23
+    when :rm_is; args << :rm << :stype << :shifti
24
+    when :rm_rs; args << :rm << :stype << :rs
25
+    when :mem_rn_rm; args << :rn << :rm << :rsx << :u
26
+    when :mem_rn_i8_12; args << :rn << :i8_12 << :u
27
+    when :mem_rn_rms; args << :rn << :rm << :stype << :shifti << :u
28
+    when :mem_rn_i12; args << :rn << :i12 << :u
29
+    end
30
+
31
+    (args & @fields_mask.keys).each { |f|
32
+      o.fields[f] = [@fields_mask[f], @fields_shift[f]]
33
+    }
34
+
35
+    @opcode_list << o
36
+  end
37
+
38
+  def addop_data_s(name, op, a1, a2, *h)
39
+    addop name, op | (1 << 25), a1, a2, :i8_r, :rotate, *h
40
+    addop name, op, a1, a2, :rm_is, *h
41
+    addop name, op | (1 << 4), a1, a2, :rm_rs, *h
42
+  end
43
+  def addop_data(name, op, a1, a2)
44
+    addop_data_s name, op << 21, a1, a2
45
+    addop_data_s name+'s', (op << 21) | (1 << 20), a1, a2, :cond_name_off => name.length
46
+  end
47
+
48
+  def addop_load_puw(name, op, *a)
49
+    addop name, op, {:baseincr => :post}, :rd, :u, *a
50
+    addop name, op | (1 << 24), :rd, :u, *a
51
+    addop name, op | (1 << 24) | (1 << 21), {:baseincr => :pre}, :rd, :u, *a
52
+  end
53
+  def addop_load_lsh_o(name, op)
54
+    addop_load_puw name, op, :rsz, :mem_rn_rm, {:cond_name_off => 3}
55
+    addop_load_puw name, op | (1 << 22), :mem_rn_i8_12, {:cond_name_off => 3}
56
+  end
57
+  def addop_load_lsh
58
+    op = 9 << 4
59
+    addop_load_lsh_o 'strh',  op | (1 << 5)
60
+    addop_load_lsh_o 'ldrd',  op | (1 << 6)
61
+    addop_load_lsh_o 'strd',  op | (1 << 6) | (1 << 5)
62
+    addop_load_lsh_o 'ldrh',  op | (1 << 20) | (1 << 5)
63
+    addop_load_lsh_o 'ldrsb', op | (1 << 20) | (1 << 6)
64
+    addop_load_lsh_o 'ldrsh', op | (1 << 20) | (1 << 6) | (1 << 5)
65
+  end
66
+
67
+  def addop_load_puwt(name, op, *a)
68
+    addop_load_puw name, op, *a
69
+    addop name+'t', op | (1 << 21), {:baseincr => :post, :cond_name_off => name.length}, :rd, :u, *a
70
+  end
71
+  def addop_load_o(name, op, *a)
72
+    addop_load_puwt name, op, :mem_rn_i12, *a
73
+    addop_load_puwt name, op | (1 << 25), :mem_rn_rms, *a
74
+  end
75
+  def addop_load(name, op)
76
+    addop_load_o name, op
77
+    addop_load_o name+'b', op | (1 << 22), :cond_name_off => name.length
78
+  end
79
+
80
+  def addop_ldm_go(name, op, *a)
81
+    addop name, op, :rn, :reglist, {:cond_name_off => 3}, *a
82
+  end
83
+  def addop_ldm_w(name, op, *a)
84
+    addop_ldm_go name, op, *a		# base reg untouched
85
+    addop_ldm_go name, op | (1 << 21), {:baseincr => :post}, *a	# base updated
86
+  end
87
+  def addop_ldm_s(name, op)
88
+    addop_ldm_w name, op			# transfer regs
89
+    addop_ldm_w name, op | (1 << 22), :usermoderegs	# transfer usermode regs
90
+  end
91
+  def addop_ldm_p(name, op)
92
+    addop_ldm_s name+'a', op		# target memory included
93
+    addop_ldm_s name+'b', op | (1 << 24)	# target memory excluded, transfer starts at next addr
94
+  end
95
+  def addop_ldm_u(name, op)
96
+    addop_ldm_p name+'d', op		# transfer made downward
97
+    addop_ldm_p name+'i', op | (1 << 23)	# transfer made upward
98
+  end
99
+  def addop_ldm(name, op)
100
+    addop_ldm_u name, op
101
+  end
102
+
103
+  # ARMv6 instruction set, aka arm7/arm9
104
+  def init_arm_v6
105
+    @opcode_list = []
106
+    @valid_props << :baseincr << :cond << :cond_name_off << :usermoderegs <<
107
+        :tothumb << :tojazelle
108
+    @valid_args.concat [:rn, :rd, :rm, :crn, :crd, :crm, :cpn, :reglist, :i24,
109
+      :rm_rs, :rm_is, :i8_r, :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12]
110
+    @fields_mask.update :rn => 0xf, :rd => 0xf, :rs => 0xf, :rm => 0xf,
111
+      :crn => 0xf, :crd => 0xf, :crm => 0xf, :cpn => 0xf,
112
+      :rnx => 0xf, :rdx => 0xf, :rsx => 0xf,
113
+      :shifti => 0x1f, :stype => 3, :rotate => 0xf, :reglist => 0xffff,
114
+      :i8 => 0xff, :i12 => 0xfff, :i24 => 0xff_ffff, :i8_12 => 0xf0f,
115
+      :u => 1, :mask => 0xf, :sbo => 0xf, :cond => 0xf
116
+
117
+    @fields_shift.update :rn => 16, :rd => 12, :rs => 8, :rm => 0,
118
+      :crn => 16, :crd => 12, :crm => 0, :cpn => 8,
119
+      :rnx => 16, :rdx => 12, :rsx => 8,
120
+      :shifti => 7, :stype => 5, :rotate => 8, :reglist => 0,
121
+      :i8 => 0, :i12 => 0, :i24 => 0, :i8_12 => 0,
122
+      :u => 23, :mask => 16, :sbo => 12, :cond => 28
123
+    
124
+    addop_data 'and', 0,  :rd, :rn
125
+    addop_data 'eor', 1,  :rd, :rn
126
+    addop_data 'xor', 1,  :rd, :rn
127
+    addop_data 'sub', 2,  :rd, :rn
128
+    addop_data 'rsb', 3,  :rd, :rn
129
+    addop_data 'add', 4,  :rd, :rn
130
+    addop_data 'adc', 5,  :rd, :rn
131
+    addop_data 'sbc', 6,  :rd, :rn
132
+    addop_data 'rsc', 7,  :rd, :rn
133
+    addop_data 'tst', 8,  :rdx, :rn
134
+    addop_data 'teq', 9,  :rdx, :rn
135
+    addop_data 'cmp', 10, :rdx, :rn
136
+    addop_data 'cmn', 11, :rdx, :rn
137
+    addop_data 'orr', 12, :rd, :rn
138
+    addop_data 'or',  12, :rd, :rn
139
+    addop_data 'mov', 13, :rd, :rnx
140
+    addop_data 'bic', 14, :rd, :rn
141
+    addop_data 'mvn', 15, :rd, :rnx
142
+    
143
+    addop 'b',  0b1010 << 24, :setip, :stopexec, :i24
144