metasm 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (192) hide show
  1. data/BUGS +11 -0
  2. data/CREDITS +17 -0
  3. data/README +270 -0
  4. data/TODO +114 -0
  5. data/doc/code_organisation.txt +146 -0
  6. data/doc/const_missing.txt +16 -0
  7. data/doc/core_classes.txt +75 -0
  8. data/doc/feature_list.txt +53 -0
  9. data/doc/index.txt +59 -0
  10. data/doc/install_notes.txt +170 -0
  11. data/doc/style.css +3 -0
  12. data/doc/use_cases.txt +18 -0
  13. data/lib/metasm.rb +80 -0
  14. data/lib/metasm/arm.rb +12 -0
  15. data/lib/metasm/arm/debug.rb +39 -0
  16. data/lib/metasm/arm/decode.rb +167 -0
  17. data/lib/metasm/arm/encode.rb +77 -0
  18. data/lib/metasm/arm/main.rb +75 -0
  19. data/lib/metasm/arm/opcodes.rb +177 -0
  20. data/lib/metasm/arm/parse.rb +130 -0
  21. data/lib/metasm/arm/render.rb +55 -0
  22. data/lib/metasm/compile_c.rb +1457 -0
  23. data/lib/metasm/dalvik.rb +8 -0
  24. data/lib/metasm/dalvik/decode.rb +196 -0
  25. data/lib/metasm/dalvik/main.rb +60 -0
  26. data/lib/metasm/dalvik/opcodes.rb +366 -0
  27. data/lib/metasm/decode.rb +213 -0
  28. data/lib/metasm/decompile.rb +2659 -0
  29. data/lib/metasm/disassemble.rb +2068 -0
  30. data/lib/metasm/disassemble_api.rb +1280 -0
  31. data/lib/metasm/dynldr.rb +1329 -0
  32. data/lib/metasm/encode.rb +333 -0
  33. data/lib/metasm/exe_format/a_out.rb +194 -0
  34. data/lib/metasm/exe_format/autoexe.rb +82 -0
  35. data/lib/metasm/exe_format/bflt.rb +189 -0
  36. data/lib/metasm/exe_format/coff.rb +455 -0
  37. data/lib/metasm/exe_format/coff_decode.rb +901 -0
  38. data/lib/metasm/exe_format/coff_encode.rb +1078 -0
  39. data/lib/metasm/exe_format/dex.rb +457 -0
  40. data/lib/metasm/exe_format/dol.rb +145 -0
  41. data/lib/metasm/exe_format/elf.rb +923 -0
  42. data/lib/metasm/exe_format/elf_decode.rb +979 -0
  43. data/lib/metasm/exe_format/elf_encode.rb +1375 -0
  44. data/lib/metasm/exe_format/macho.rb +827 -0
  45. data/lib/metasm/exe_format/main.rb +228 -0
  46. data/lib/metasm/exe_format/mz.rb +164 -0
  47. data/lib/metasm/exe_format/nds.rb +172 -0
  48. data/lib/metasm/exe_format/pe.rb +437 -0
  49. data/lib/metasm/exe_format/serialstruct.rb +246 -0
  50. data/lib/metasm/exe_format/shellcode.rb +114 -0
  51. data/lib/metasm/exe_format/xcoff.rb +167 -0
  52. data/lib/metasm/gui.rb +23 -0
  53. data/lib/metasm/gui/cstruct.rb +373 -0
  54. data/lib/metasm/gui/dasm_coverage.rb +199 -0
  55. data/lib/metasm/gui/dasm_decomp.rb +369 -0
  56. data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
  57. data/lib/metasm/gui/dasm_graph.rb +1354 -0
  58. data/lib/metasm/gui/dasm_hex.rb +543 -0
  59. data/lib/metasm/gui/dasm_listing.rb +599 -0
  60. data/lib/metasm/gui/dasm_main.rb +906 -0
  61. data/lib/metasm/gui/dasm_opcodes.rb +291 -0
  62. data/lib/metasm/gui/debug.rb +1228 -0
  63. data/lib/metasm/gui/gtk.rb +884 -0
  64. data/lib/metasm/gui/qt.rb +495 -0
  65. data/lib/metasm/gui/win32.rb +3004 -0
  66. data/lib/metasm/gui/x11.rb +621 -0
  67. data/lib/metasm/ia32.rb +14 -0
  68. data/lib/metasm/ia32/compile_c.rb +1523 -0
  69. data/lib/metasm/ia32/debug.rb +193 -0
  70. data/lib/metasm/ia32/decode.rb +1167 -0
  71. data/lib/metasm/ia32/decompile.rb +564 -0
  72. data/lib/metasm/ia32/encode.rb +314 -0
  73. data/lib/metasm/ia32/main.rb +233 -0
  74. data/lib/metasm/ia32/opcodes.rb +872 -0
  75. data/lib/metasm/ia32/parse.rb +327 -0
  76. data/lib/metasm/ia32/render.rb +91 -0
  77. data/lib/metasm/main.rb +1193 -0
  78. data/lib/metasm/mips.rb +11 -0
  79. data/lib/metasm/mips/compile_c.rb +7 -0
  80. data/lib/metasm/mips/decode.rb +253 -0
  81. data/lib/metasm/mips/encode.rb +51 -0
  82. data/lib/metasm/mips/main.rb +72 -0
  83. data/lib/metasm/mips/opcodes.rb +443 -0
  84. data/lib/metasm/mips/parse.rb +51 -0
  85. data/lib/metasm/mips/render.rb +43 -0
  86. data/lib/metasm/os/gnu_exports.rb +270 -0
  87. data/lib/metasm/os/linux.rb +1112 -0
  88. data/lib/metasm/os/main.rb +1686 -0
  89. data/lib/metasm/os/remote.rb +527 -0
  90. data/lib/metasm/os/windows.rb +2027 -0
  91. data/lib/metasm/os/windows_exports.rb +745 -0
  92. data/lib/metasm/parse.rb +876 -0
  93. data/lib/metasm/parse_c.rb +3938 -0
  94. data/lib/metasm/pic16c/decode.rb +42 -0
  95. data/lib/metasm/pic16c/main.rb +17 -0
  96. data/lib/metasm/pic16c/opcodes.rb +68 -0
  97. data/lib/metasm/ppc.rb +11 -0
  98. data/lib/metasm/ppc/decode.rb +264 -0
  99. data/lib/metasm/ppc/decompile.rb +251 -0
  100. data/lib/metasm/ppc/encode.rb +51 -0
  101. data/lib/metasm/ppc/main.rb +129 -0
  102. data/lib/metasm/ppc/opcodes.rb +410 -0
  103. data/lib/metasm/ppc/parse.rb +52 -0
  104. data/lib/metasm/preprocessor.rb +1277 -0
  105. data/lib/metasm/render.rb +130 -0
  106. data/lib/metasm/sh4.rb +8 -0
  107. data/lib/metasm/sh4/decode.rb +336 -0
  108. data/lib/metasm/sh4/main.rb +292 -0
  109. data/lib/metasm/sh4/opcodes.rb +381 -0
  110. data/lib/metasm/x86_64.rb +12 -0
  111. data/lib/metasm/x86_64/compile_c.rb +1025 -0
  112. data/lib/metasm/x86_64/debug.rb +59 -0
  113. data/lib/metasm/x86_64/decode.rb +268 -0
  114. data/lib/metasm/x86_64/encode.rb +264 -0
  115. data/lib/metasm/x86_64/main.rb +135 -0
  116. data/lib/metasm/x86_64/opcodes.rb +118 -0
  117. data/lib/metasm/x86_64/parse.rb +68 -0
  118. data/misc/bottleneck.rb +61 -0
  119. data/misc/cheader-findpppath.rb +58 -0
  120. data/misc/hexdiff.rb +74 -0
  121. data/misc/hexdump.rb +55 -0
  122. data/misc/metasm-all.rb +13 -0
  123. data/misc/objdiff.rb +47 -0
  124. data/misc/objscan.rb +40 -0
  125. data/misc/pdfparse.rb +661 -0
  126. data/misc/ppc_pdf2oplist.rb +192 -0
  127. data/misc/tcp_proxy_hex.rb +84 -0
  128. data/misc/txt2html.rb +440 -0
  129. data/samples/a.out.rb +31 -0
  130. data/samples/asmsyntax.rb +77 -0
  131. data/samples/bindiff.rb +555 -0
  132. data/samples/compilation-steps.rb +49 -0
  133. data/samples/cparser_makestackoffset.rb +55 -0
  134. data/samples/dasm-backtrack.rb +38 -0
  135. data/samples/dasmnavig.rb +318 -0
  136. data/samples/dbg-apihook.rb +228 -0
  137. data/samples/dbghelp.rb +143 -0
  138. data/samples/disassemble-gui.rb +102 -0
  139. data/samples/disassemble.rb +133 -0
  140. data/samples/dump_upx.rb +95 -0
  141. data/samples/dynamic_ruby.rb +1929 -0
  142. data/samples/elf_list_needed.rb +46 -0
  143. data/samples/elf_listexports.rb +33 -0
  144. data/samples/elfencode.rb +25 -0
  145. data/samples/exeencode.rb +128 -0
  146. data/samples/factorize-headers-elfimports.rb +77 -0
  147. data/samples/factorize-headers-peimports.rb +109 -0
  148. data/samples/factorize-headers.rb +43 -0
  149. data/samples/gdbclient.rb +583 -0
  150. data/samples/generate_libsigs.rb +102 -0
  151. data/samples/hotfix_gtk_dbg.rb +59 -0
  152. data/samples/install_win_env.rb +78 -0
  153. data/samples/lindebug.rb +924 -0
  154. data/samples/linux_injectsyscall.rb +95 -0
  155. data/samples/machoencode.rb +31 -0
  156. data/samples/metasm-shell.rb +91 -0
  157. data/samples/pe-hook.rb +69 -0
  158. data/samples/pe-ia32-cpuid.rb +203 -0
  159. data/samples/pe-mips.rb +35 -0
  160. data/samples/pe-shutdown.rb +78 -0
  161. data/samples/pe-testrelocs.rb +51 -0
  162. data/samples/pe-testrsrc.rb +24 -0
  163. data/samples/pe_listexports.rb +31 -0
  164. data/samples/peencode.rb +19 -0
  165. data/samples/peldr.rb +494 -0
  166. data/samples/preprocess-flatten.rb +19 -0
  167. data/samples/r0trace.rb +308 -0
  168. data/samples/rubstop.rb +399 -0
  169. data/samples/scan_pt_gnu_stack.rb +54 -0
  170. data/samples/scanpeexports.rb +62 -0
  171. data/samples/shellcode-c.rb +40 -0
  172. data/samples/shellcode-dynlink.rb +146 -0
  173. data/samples/source.asm +34 -0
  174. data/samples/struct_offset.rb +47 -0
  175. data/samples/testpe.rb +32 -0
  176. data/samples/testraw.rb +45 -0
  177. data/samples/win32genloader.rb +132 -0
  178. data/samples/win32hooker-advanced.rb +169 -0
  179. data/samples/win32hooker.rb +96 -0
  180. data/samples/win32livedasm.rb +33 -0
  181. data/samples/win32remotescan.rb +133 -0
  182. data/samples/wintrace.rb +92 -0
  183. data/tests/all.rb +8 -0
  184. data/tests/dasm.rb +39 -0
  185. data/tests/dynldr.rb +35 -0
  186. data/tests/encodeddata.rb +132 -0
  187. data/tests/ia32.rb +82 -0
  188. data/tests/mips.rb +116 -0
  189. data/tests/parse_c.rb +239 -0
  190. data/tests/preprocessor.rb +269 -0
  191. data/tests/x86_64.rb +62 -0
  192. metadata +255 -0
@@ -0,0 +1,8 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/main'
8
+ require 'metasm/dalvik/decode'
@@ -0,0 +1,196 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+ require 'metasm/dalvik/opcodes'
7
+ require 'metasm/decode'
8
+
9
+ module Metasm
10
+ class Dalvik
11
+ def build_bin_lookaside
12
+ end
13
+
14
+ def decode_findopcode(edata)
15
+ return if edata.ptr >= edata.data.length
16
+ di = DecodedInstruction.new(self)
17
+ di.opcode = opcode_list[edata.decode_imm(:u16, @endianness) & 0xff]
18
+ edata.ptr -= 2
19
+ di
20
+ end
21
+
22
+ def decode_instr_op(edata, di)
23
+ op = di.opcode
24
+ di.instruction.opname = op.name
25
+
26
+ val = [edata.decode_imm(:u16, @endianness)]
27
+
28
+ op.args.each { |a|
29
+ di.instruction.args << case a
30
+ when :i16
31
+ val << edata.decode_imm(:i16, @endianness)
32
+ Expression[val.last]
33
+ when :u16
34
+ val << edata.decode_imm(:u16, @endianness)
35
+ Expression[val.last]
36
+ when :r16
37
+ val << edata.decode_imm(:u16, @endianness)
38
+ Reg.new(val.last)
39
+ when :i16_32hi
40
+ val << edata.decode_imm(:i16, @endianness)
41
+ Expression[val.last << 16]
42
+ when :i16_64hi
43
+ val << edata.decode_imm(:i16, @endianness)
44
+ Expression[val.last << 48]
45
+ when :i32
46
+ val << edata.decode_imm(:u16, @endianness)
47
+ val << edata.decode_imm(:i16, @endianness)
48
+ Expression[val[-2] | (val[-1] << 16)]
49
+ when :u32
50
+ val << edata.decode_imm(:u16, @endianness)
51
+ val << edata.decode_imm(:u16, @endianness)
52
+ Expression[val[-2] | (val[-1] << 16)]
53
+ when :u64
54
+ val << edata.decode_imm(:u16, @endianness)
55
+ val << edata.decode_imm(:u16, @endianness)
56
+ val << edata.decode_imm(:u16, @endianness)
57
+ val << edata.decode_imm(:u16, @endianness)
58
+ Expression[val[-4] | (val[-3] << 16) | (val[-2] << 32) | (val[-1] << 48)]
59
+ when :ra
60
+ Reg.new((val[0] >> 8) & 0xf)
61
+ when :rb
62
+ Reg.new((val[0] >> 12) & 0xf)
63
+ when :ib
64
+ Expression[Expression.make_signed((val[0] >> 12) & 0xf, 4)]
65
+ when :raa
66
+ Reg.new((val[0] >> 8) & 0xff)
67
+ when :iaa
68
+ Expression[Expression.make_signed((val[0] >> 8) & 0xff, 8)]
69
+ when :rbb
70
+ val[1] ||= edata.decode_imm(:u16, @endianness)
71
+ Reg.new(val[1] & 0xff)
72
+ when :ibb
73
+ val[1] ||= edata.decode_imm(:u16, @endianness)
74
+ Expression[Expression.make_signed(val[1] & 0xff, 8)]
75
+ when :rcc
76
+ val[1] ||= edata.decode_imm(:u16, @endianness)
77
+ Reg.new((val[1] >> 8) & 0xff)
78
+ when :icc
79
+ val[1] ||= edata.decode_imm(:u16, @endianness)
80
+ Expression[Expression.make_signed((val[1] >> 8) & 0xff, 8)]
81
+ when :rlist4, :rlist5
82
+ cnt = (val[0] >> 12) & 0xf
83
+ val << edata.decode_imm(:u16, @endianness)
84
+ [cnt, 4].min.times {
85
+ di.instruction.args << Reg.new(val[-1] & 0xf)
86
+ val[-1] >>= 4
87
+ }
88
+ di.instruction.args << Reg.new((val[0] >> 8) & 0xf) if cnt > 4
89
+ next
90
+ when :rlist16
91
+ cnt = (val[0] >> 8) & 0xff
92
+ val << edata.decode_imm(:u16, @endianness)
93
+ cnt.times { |c|
94
+ di.instruction.args << Reg.new(val[-1] + c)
95
+ }
96
+ next
97
+ when :m16
98
+ val << edata.decode_imm(:u16, @endianness)
99
+ Method.new(@dex, val.last)
100
+ else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
101
+ end
102
+ }
103
+
104
+ di.bin_length = val.length*2
105
+
106
+ di
107
+ end
108
+
109
+ def backtrace_binding
110
+ @backtrace_binding ||= init_backtrace_binding
111
+ end
112
+
113
+ def init_backtrace_binding
114
+ @backtrace_binding ||= {}
115
+ sz = @size/8
116
+ @opcode_list.each { |op|
117
+ case op.name
118
+ when /invoke/
119
+ @backtrace_binding[op.name] = lambda { |di, *args| {
120
+ :callstack => Expression[:callstack, :-, sz],
121
+ Indirection[:callstack, sz] => Expression[di.next_addr]
122
+ } }
123
+ when /return/
124
+ @backtrace_binding[op.name] = lambda { |di, *args| {
125
+ :callstack => Expression[:callstack, :+, sz]
126
+ } }
127
+ end
128
+ }
129
+ @backtrace_binding
130
+ end
131
+
132
+ def get_backtrace_binding(di)
133
+ a = di.instruction.args.map { |arg|
134
+ case arg
135
+ when Reg; arg.symbolic
136
+ else arg
137
+ end
138
+ }
139
+
140
+ if binding = backtrace_binding[di.opcode.name]
141
+ bd = binding[di, *a]
142
+ else
143
+ puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
144
+ # assume nothing except the 1st arg is modified
145
+ case a[0]
146
+ when Indirection, Symbol; { a[0] => Expression::Unknown }
147
+ when Expression; (x = a[0].externals.first) ? { x => Expression::Unknown } : {}
148
+ else {}
149
+ end.update(:incomplete_binding => Expression[1])
150
+ end
151
+
152
+ end
153
+
154
+ def get_xrefs_x(dasm, di)
155
+ if di.opcode.props[:saveip]
156
+ m = di.instruction.args.first
157
+ if m.kind_of? Method and m.off
158
+ [m.off]
159
+ else
160
+ [:default]
161
+ end
162
+ elsif di.opcode.props[:setip]
163
+ if di.opcode.name =~ /return/
164
+ [Indirection[:callstack, @size/8]]
165
+ else
166
+ [] # [di.instruction.args.last]
167
+ end
168
+ else
169
+ []
170
+ end
171
+ end
172
+
173
+ # returns a DecodedFunction suitable for :default
174
+ # uses disassembler_default_bt{for/bind}_callback
175
+ def disassembler_default_func
176
+ df = DecodedFunction.new
177
+ ra = Indirection[:callstack, @size/8]
178
+ df.backtracked_for << BacktraceTrace.new(ra, :default, ra, :x, nil)
179
+ df.backtrace_binding[:callstack] = Expression[:callstack, :+, @size/8]
180
+ df.btfor_callback = lambda { |dasm, btfor, funcaddr, calladdr|
181
+ if funcaddr != :default
182
+ btfor
183
+ elsif di = dasm.decoded[calladdr] and di.opcode.props[:saveip]
184
+ btfor
185
+ else []
186
+ end
187
+ }
188
+
189
+ df
190
+ end
191
+
192
+ def backtrace_is_function_return(expr, di=nil)
193
+ expr and Expression[expr] == Expression[Indirection[:callstack, @size/8]]
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,60 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/main'
8
+
9
+ module Metasm
10
+ class Dalvik < CPU
11
+ class Reg
12
+ attr_accessor :i
13
+ def initialize(i)
14
+ @i = i
15
+ end
16
+
17
+ def symbolic
18
+ "r#@i".to_sym
19
+ end
20
+
21
+ def to_s
22
+ "r#@i"
23
+ end
24
+ end
25
+
26
+ class Method
27
+ attr_accessor :dex, :midx, :off
28
+ def initialize(dex, midx)
29
+ @dex = dex
30
+ @midx = midx
31
+ if @dex and m = @dex.methods[midx] and c = @dex.classes[m.classidx] and c.data and
32
+ me = (c.data.direct_methods+c.data.virtual_methods).find { |mm| mm.method == m }
33
+ @off = me.codeoff + me.code.insns_off
34
+ end
35
+ end
36
+
37
+ def to_s
38
+ if @dex and m = @dex.methods[@midx]
39
+ @dex.types[m.classidx] + '->' + @dex.strings[m.nameidx]
40
+ #dex.encoded.inv_export[@off]
41
+ else
42
+ "method_#@midx"
43
+ end
44
+ end
45
+ end
46
+
47
+ def initialize(*args)
48
+ super()
49
+ @size = args.grep(Integer).first || 32
50
+ @dex = args.grep(ExeFormat).first
51
+ @endianness = args.delete(:little) || args.delete(:big) || (@dex ? @dex.endianness : :little)
52
+ end
53
+
54
+ def init_opcode_list
55
+ init_latest
56
+ @opcode_list
57
+ end
58
+ end
59
+ end
60
+
@@ -0,0 +1,366 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2006-2009 Yoann GUILLOT
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+ # the Dalvik binary format, aka android java backend bytecode
7
+ # this file was generated using the android source tree, as reference,
8
+ # specifically dalvik/libdex/InstrUtils.c
9
+
10
+ # the binary opcode format is 16 bit word-based
11
+ # the opcode number is in the low-order byte, and determines the
12
+ # argument format, which may take up to 4 other words
13
+
14
+ require 'metasm/dalvik/main'
15
+
16
+ module Metasm
17
+ class Dalvik
18
+ OPCODES = %w[nop move move_from16 move_16 move_wide move_wide_from16
19
+ move_wide_16 move_object move_object_from16 move_object_16 move_result
20
+ move_result_wide move_result_object move_exception
21
+ return_void return return_wide return_object
22
+ const_4 const_16 const const_high16 const_wide_16 const_wide_32
23
+ const_wide const_wide_high16 const_string const_string_jumbo const_class
24
+ monitor_enter monitor_exit check_cast instance_of array_length
25
+ new_instance new_array filled_new_array filled_new_array_range fill_array_data
26
+ throw goto goto_16 goto_32 packed_switch sparse_switch
27
+ cmpl_float cmpg_float cmpl_double cmpg_double cmp_long
28
+ if_eq if_ne if_lt if_ge if_gt if_le if_eqz if_nez if_ltz if_gez if_gtz if_lez
29
+ unused_3e unused_3f unused_40 unused_41 unused_42 unused_43
30
+ aget aget_wide aget_object aget_boolean aget_byte aget_char aget_short
31
+ aput aput_wide aput_object aput_boolean aput_byte aput_char aput_short
32
+ iget iget_wide iget_object iget_boolean iget_byte iget_char iget_short
33
+ iput iput_wide iput_object iput_boolean iput_byte iput_char iput_short
34
+ sget sget_wide sget_object sget_boolean sget_byte sget_char sget_short
35
+ sput sput_wide sput_object sput_boolean sput_byte sput_char sput_short
36
+ invoke_virtual invoke_super invoke_direct invoke_static invoke_interface
37
+ unused_73
38
+ invoke_virtual_range invoke_super_range invoke_direct_range invoke_static_range invoke_interface_range
39
+ unused_79 unused_7a
40
+ neg_int not_int neg_long not_long neg_float neg_double
41
+ int_to_long int_to_float int_to_double long_to_int long_to_float long_to_double
42
+ float_to_int float_to_long float_to_double double_to_int double_to_long
43
+ double_to_float int_to_byte int_to_char int_to_short
44
+ add_int sub_int mul_int div_int rem_int and_int or_int xor_int shl_int shr_int ushr_int
45
+ add_long sub_long mul_long div_long rem_long and_long or_long xor_long shl_long shr_long ushr_long
46
+ add_float sub_float mul_float div_float rem_float
47
+ add_double sub_double mul_double div_double rem_double
48
+ add_int_2addr sub_int_2addr mul_int_2addr div_int_2addr rem_int_2addr
49
+ and_int_2addr or_int_2addr xor_int_2addr shl_int_2addr shr_int_2addr ushr_int_2addr
50
+ add_long_2addr sub_long_2addr mul_long_2addr div_long_2addr rem_long_2addr
51
+ and_long_2addr or_long_2addr xor_long_2addr shl_long_2addr shr_long_2addr ushr_long_2addr
52
+ add_float_2addr sub_float_2addr mul_float_2addr div_float_2addr rem_float_2addr
53
+ add_double_2addr sub_double_2addr mul_double_2addr div_double_2addr rem_double_2addr
54
+ add_int_lit16 rsub_int mul_int_lit16 div_int_lit16 rem_int_lit16 and_int_lit16 or_int_lit16 xor_int_lit16
55
+ add_int_lit8 rsub_int_lit8 mul_int_lit8 div_int_lit8 rem_int_lit8 and_int_lit8 or_int_lit8 xor_int_lit8
56
+ shl_int_lit8 shr_int_lit8 ushr_int_lit8
57
+ unused_e3 unused_e4 unused_e5 unused_e6 unused_e7 unused_e8 unused_e9 unused_ea unused_eb unused_ec
58
+ throw_verification_error execute_inline unused_ef invoke_direct_empty unused_f1
59
+ iget_quick iget_wide_quick iget_object_quick iput_quick iput_wide_quick iput_object_quick
60
+ invoke_virtual_quick invoke_virtual_quick_range invoke_super_quick invoke_super_quick_range
61
+ unused_fc unused_fd unused_fe unused_ff]
62
+
63
+ def init_dalvik
64
+ @valid_props << :canthrow
65
+ @valid_args = [:i16, :i16_32hi, :i16_64hi, :i32, :iaa, :ib, :icc, :u16, :u32, :u64,
66
+ :r16, :ra, :raa, :rb, :rbb, :rcc, :rlist16, :rlist4, :rlist5, :m16]
67
+ @opcode_list = []
68
+
69
+ OPCODES.each_with_index { |n, b|
70
+ op = Opcode.new(n, b)
71
+ addop_args(op)
72
+ addop_props(op)
73
+ @opcode_list << op
74
+ }
75
+
76
+ raise "Internal error #{@opcode_list.length}" if @opcode_list.length != 256
77
+ end
78
+ alias init_latest init_dalvik
79
+
80
+ def addop_args(op)
81
+ fmt = case op.name
82
+ when 'goto'
83
+ :fmt10t
84
+ when 'nop', 'return_void'
85
+ :fmt10x
86
+ when 'const_4'
87
+ :fmt11n
88
+ when 'const_high16'
89
+ :fmt21h
90
+ when 'const_wide_high16'
91
+ :fmt21hh
92
+ when 'move_result', 'move_result_wide', 'move_result_object',
93
+ 'move_exception', 'return', 'return_wide',
94
+ 'return_object', 'monitor_enter', 'monitor_exit',
95
+ 'throw'
96
+ :fmt11x
97
+ when 'move', 'move_wide', 'move_object', 'array_length',
98
+ 'neg_int', 'not_int', 'neg_long', 'not_long',
99
+ 'neg_float', 'neg_double', 'int_to_long',
100
+ 'int_to_float', 'int_to_double', 'long_to_int',
101
+ 'long_to_float', 'long_to_double', 'float_to_int',
102
+ 'float_to_long', 'float_to_double', 'double_to_int',
103
+ 'double_to_long', 'double_to_float', 'int_to_byte',
104
+ 'int_to_char', 'int_to_short', 'add_int_2addr',
105
+ 'sub_int_2addr', 'mul_int_2addr', 'div_int_2addr',
106
+ 'rem_int_2addr', 'and_int_2addr', 'or_int_2addr',
107
+ 'xor_int_2addr', 'shl_int_2addr', 'shr_int_2addr',
108
+ 'ushr_int_2addr', 'add_long_2addr', 'sub_long_2addr',
109
+ 'mul_long_2addr', 'div_long_2addr', 'rem_long_2addr',
110
+ 'and_long_2addr', 'or_long_2addr', 'xor_long_2addr',
111
+ 'shl_long_2addr', 'shr_long_2addr', 'ushr_long_2addr',
112
+ 'add_float_2addr', 'sub_float_2addr', 'mul_float_2addr',
113
+ 'div_float_2addr', 'rem_float_2addr',
114
+ 'add_double_2addr', 'sub_double_2addr',
115
+ 'mul_double_2addr', 'div_double_2addr',
116
+ 'rem_double_2addr'
117
+ :fmt12x
118
+ when 'goto_16'
119
+ :fmt20t
120
+ when 'goto_32'
121
+ :fmt30t
122
+ when 'const_string', 'const_class', 'check_cast',
123
+ 'new_instance', 'sget', 'sget_wide', 'sget_object',
124
+ 'sget_boolean', 'sget_byte', 'sget_char', 'sget_short',
125
+ 'sput', 'sput_wide', 'sput_object', 'sput_boolean',
126
+ 'sput_byte', 'sput_char', 'sput_short'
127
+ :fmt21c
128
+ when 'const_16', 'const_wide_16'
129
+ :fmt21s
130
+ when 'if_eqz', 'if_nez', 'if_ltz', 'if_gez', 'if_gtz', 'if_lez'
131
+ :fmt21t
132
+ when 'fill_array_data', 'packed_switch', 'sparse_switch'
133
+ :fmt31t
134
+ when 'add_int_lit8', 'rsub_int_lit8', 'mul_int_lit8',
135
+ 'div_int_lit8', 'rem_int_lit8', 'and_int_lit8',
136
+ 'or_int_lit8', 'xor_int_lit8', 'shl_int_lit8',
137
+ 'shr_int_lit8', 'ushr_int_lit8'
138
+ :fmt22b
139
+ when 'instance_of', 'new_array', 'iget', 'iget_wide',
140
+ 'iget_object', 'iget_boolean', 'iget_byte',
141
+ 'iget_char', 'iget_short', 'iput', 'iput_wide',
142
+ 'iput_object', 'iput_boolean', 'iput_byte',
143
+ 'iput_char', 'iput_short'
144
+ :fmt22c
145
+ when 'add_int_lit16', 'rsub_int', 'mul_int_lit16',
146
+ 'div_int_lit16', 'rem_int_lit16', 'and_int_lit16',
147
+ 'or_int_lit16', 'xor_int_lit16'
148
+ :fmt22s
149
+ when 'if_eq', 'if_ne', 'if_lt', 'if_ge', 'if_gt', 'if_le'
150
+ :fmt22t
151
+ when 'move_from16', 'move_wide_from16', 'move_object_from16'
152
+ :fmt22x
153
+ when 'cmpl_float', 'cmpg_float', 'cmpl_double', 'cmpg_double',
154
+ 'cmp_long', 'aget', 'aget_wide', 'aget_object',
155
+ 'aget_boolean', 'aget_byte', 'aget_char', 'aget_short',
156
+ 'aput', 'aput_wide', 'aput_object', 'aput_boolean',
157
+ 'aput_byte', 'aput_char', 'aput_short', 'add_int',
158
+ 'sub_int', 'mul_int', 'div_int', 'rem_int', 'and_int',
159
+ 'or_int', 'xor_int', 'shl_int', 'shr_int', 'ushr_int',
160
+ 'add_long', 'sub_long', 'mul_long', 'div_long',
161
+ 'rem_long', 'and_long', 'or_long', 'xor_long',
162
+ 'shl_long', 'shr_long', 'ushr_long', 'add_float',
163
+ 'sub_float', 'mul_float', 'div_float', 'rem_float',
164
+ 'add_double', 'sub_double', 'mul_double', 'div_double',
165
+ 'rem_double'
166
+ :fmt23x
167
+ when 'const', 'const_wide_32'
168
+ :fmt31i
169
+ when 'const_string_jumbo'
170
+ :fmt31c
171
+ when 'move_16', 'move_wide_16', 'move_object_16'
172
+ :fmt32x
173
+ when 'filled_new_array'
174
+ :fmt35ca
175
+ when 'invoke_virtual', 'invoke_super',
176
+ 'invoke_direct', 'invoke_static', 'invoke_interface'
177
+ :fmt35c
178
+ when 'filled_new_array_range', 'invoke_virtual_range',
179
+ 'invoke_super_range', 'invoke_direct_range',
180
+ 'invoke_static_range', 'invoke_interface_range'
181
+ :fmt3rc
182
+ when 'const_wide'
183
+ :fmt51l
184
+ when 'throw_verification_error'
185
+ :fmt20bc
186
+ when 'iget_quick', 'iget_wide_quick', 'iget_object_quick',
187
+ 'iput_quick', 'iput_wide_quick', 'iput_object_quick'
188
+ :fmt22cs
189
+ when 'invoke_virtual_quick', 'invoke_super_quick'
190
+ :fmt35ms
191
+ when 'invoke_virtual_quick_range', 'invoke_super_quick_range'
192
+ :fmt3rms
193
+ when 'execute_inline'
194
+ :fmt3inline
195
+ when 'invoke_direct_empty'
196
+ :fmt35c
197
+ when 'unused_3e', 'unused_3f', 'unused_40', 'unused_41',
198
+ 'unused_42', 'unused_43', 'unused_73', 'unused_79',
199
+ 'unused_7a', 'unused_e3', 'unused_e4', 'unused_e5',
200
+ 'unused_e6', 'unused_e7', 'unused_e8', 'unused_e9',
201
+ 'unused_ea', 'unused_eb', 'unused_ec', 'unused_ef',
202
+ 'unused_f1', 'unused_fc', 'unused_fd', 'unused_fe',
203
+ 'unused_ff'
204
+ :fmtUnknown
205
+ else
206
+ raise "Internal error #{op.name}"
207
+ end
208
+
209
+ case fmt
210
+ when :fmt10x; op.args << :iaa
211
+ when :fmt12x; op.args << :ra << :rb
212
+ when :fmt11n; op.args << :ra << :ib
213
+ when :fmt11x; op.args << :raa
214
+ when :fmt10t; op.args << :iaa
215
+ when :fmt20t; op.args << :i16
216
+ when :fmt20bc; op.args << :iaa << :u16
217
+ when :fmt21c; op.args << :raa << :u16
218
+ when :fmt22x; op.args << :raa << :r16
219
+ when :fmt21s, :fmt21t; op.args << :raa << :i16
220
+ when :fmt21h; op.args << :raa << :i16_32hi
221
+ when :fmt21hh; op.args << :raa << :i16_64hi
222
+ when :fmt23x; op.args << :raa << :rbb << :rcc
223
+ when :fmt22b; op.args << :raa << :rbb << :icc
224
+ when :fmt22s, :fmt22t; op.args << :ra << :rb << :i16
225
+ when :fmt22c, :fmt22cs; op.args << :ra << :rb << :u16
226
+ when :fmt30t; op.args << :i32
227
+ when :fmt31t, :fmt31c; op.args << :raa << :u32
228
+ when :fmt32x; op.args << :r16 << :r16
229
+ when :fmt31i; op.args << :raa << :i32
230
+ when :fmt35ca
231
+ op.args << :r16 << :rlist5
232
+ when :fmt35c, :fmt35ms
233
+ # rlist:
234
+ # nr of regs in :ib (max 5)
235
+ # regs: :ib.times { reg :i16 & 0xf ; :i16 >>= 4 }
236
+ # reg :ra if :ib == 5
237
+ op.args << :m16 << :rlist5
238
+ when :fmt3inline
239
+ op.args << :r16 << :rlist4
240
+ when :fmt3rc, :fmt3rms
241
+ # rlist = :r16, :r16+1, :r16+2, ..., :r16+:iaa-1
242
+ op.args << :r16 << :rlist16
243
+ when :fmt51l
244
+ # u64 = u16 | (u16 << 16) | ...
245
+ op.args << :raa << :u64
246
+ when :fmtUnknown
247
+ op.args << :iaa
248
+ else
249
+ raise "Internal error #{fmt.inspect}"
250
+ end
251
+ end
252
+
253
+ def addop_props(op)
254
+ case op.name
255
+ when 'nop', 'move', 'move_from16', 'move_16', 'move_wide',
256
+ 'move_wide_from16', 'move_wide_16', 'move_object',
257
+ 'move_object_from16', 'move_object_16', 'move_result',
258
+ 'move_result_wide', 'move_result_object',
259
+ 'move_exception', 'const_4', 'const_16', 'const',
260
+ 'const_high16', 'const_wide_16', 'const_wide_32',
261
+ 'const_wide', 'const_wide_high16', 'fill_array_data',
262
+ 'cmpl_float', 'cmpg_float', 'cmpl_double',
263
+ 'cmpg_double', 'cmp_long', 'neg_int', 'not_int',
264
+ 'neg_long', 'not_long', 'neg_float', 'neg_double',
265
+ 'int_to_long', 'int_to_float', 'int_to_double',
266
+ 'long_to_int', 'long_to_float', 'long_to_double',
267
+ 'float_to_int', 'float_to_long', 'float_to_double',
268
+ 'double_to_int', 'double_to_long', 'double_to_float',
269
+ 'int_to_byte', 'int_to_char', 'int_to_short', 'add_int',
270
+ 'sub_int', 'mul_int', 'and_int', 'or_int', 'xor_int',
271
+ 'shl_int', 'shr_int', 'ushr_int', 'add_long',
272
+ 'sub_long', 'mul_long', 'and_long', 'or_long',
273
+ 'xor_long', 'shl_long', 'shr_long', 'ushr_long',
274
+ 'add_float', 'sub_float', 'mul_float', 'div_float',
275
+ 'rem_float', 'add_double', 'sub_double', 'mul_double',
276
+ 'div_double', 'rem_double', 'add_int_2addr',
277
+ 'sub_int_2addr', 'mul_int_2addr', 'and_int_2addr',
278
+ 'or_int_2addr', 'xor_int_2addr', 'shl_int_2addr',
279
+ 'shr_int_2addr', 'ushr_int_2addr', 'add_long_2addr',
280
+ 'sub_long_2addr', 'mul_long_2addr', 'and_long_2addr',
281
+ 'or_long_2addr', 'xor_long_2addr', 'shl_long_2addr',
282
+ 'shr_long_2addr', 'ushr_long_2addr', 'add_float_2addr',
283
+ 'sub_float_2addr', 'mul_float_2addr', 'div_float_2addr',
284
+ 'rem_float_2addr', 'add_double_2addr',
285
+ 'sub_double_2addr', 'mul_double_2addr',
286
+ 'div_double_2addr', 'rem_double_2addr', 'add_int_lit16',
287
+ 'rsub_int', 'mul_int_lit16', 'and_int_lit16',
288
+ 'or_int_lit16', 'xor_int_lit16', 'add_int_lit8',
289
+ 'rsub_int_lit8', 'mul_int_lit8', 'and_int_lit8',
290
+ 'or_int_lit8', 'xor_int_lit8', 'shl_int_lit8',
291
+ 'shr_int_lit8', 'ushr_int_lit8'
292
+ # normal opcode, continues to next, nothing raised
293
+ when 'const_string', 'const_string_jumbo', 'const_class',
294
+ 'monitor_enter', 'monitor_exit', 'check_cast',
295
+ 'instance_of', 'array_length', 'new_instance',
296
+ 'new_array', 'filled_new_array',
297
+ 'filled_new_array_range', 'aget', 'aget_boolean',
298
+ 'aget_byte', 'aget_char', 'aget_short', 'aget_wide',
299
+ 'aget_object', 'aput', 'aput_boolean', 'aput_byte',
300
+ 'aput_char', 'aput_short', 'aput_wide', 'aput_object',
301
+ 'iget', 'iget_boolean', 'iget_byte', 'iget_char',
302
+ 'iget_short', 'iget_wide', 'iget_object', 'iput',
303
+ 'iput_boolean', 'iput_byte', 'iput_char', 'iput_short',
304
+ 'iput_wide', 'iput_object', 'sget', 'sget_boolean',
305
+ 'sget_byte', 'sget_char', 'sget_short', 'sget_wide',
306
+ 'sget_object', 'sput', 'sput_boolean', 'sput_byte',
307
+ 'sput_char', 'sput_short', 'sput_wide', 'sput_object',
308
+ 'div_int', 'rem_int', 'div_long', 'rem_long',
309
+ 'div_int_2addr', 'rem_int_2addr', 'div_long_2addr',
310
+ 'rem_long_2addr', 'div_int_lit16', 'rem_int_lit16',
311
+ 'div_int_lit8', 'rem_int_lit8'
312
+ op.props[:canthrow] = true
313
+ when 'invoke_virtual', 'invoke_virtual_range', 'invoke_super',
314
+ 'invoke_super_range', 'invoke_direct',
315
+ 'invoke_direct_range', 'invoke_static',
316
+ 'invoke_static_range', 'invoke_interface',
317
+ 'invoke_interface_range'
318
+ op.props[:canthrow] = true
319
+ op.props[:saveip] = true
320
+ op.props[:setip] = true
321
+ op.props[:stopexec] = true
322
+ when 'return_void', 'return', 'return_wide', 'return_object'
323
+ op.props[:setip] = true
324
+ op.props[:stopexec] = true
325
+ when 'throw'
326
+ op.props[:canthrow] = true
327
+ op.props[:stopexec] = true
328
+ when 'goto', 'goto_16', 'goto_32'
329
+ op.props[:setip] = true
330
+ op.props[:stopexec] = true
331
+ when 'if_eq', 'if_ne', 'if_lt', 'if_ge', 'if_gt', 'if_le',
332
+ 'if_eqz', 'if_nez', 'if_ltz', 'if_gez', 'if_gtz',
333
+ 'if_lez'
334
+ op.props[:setip] = true
335
+ when 'packed_switch', 'sparse_switch'
336
+ op.props[:setip] = true # if no table match, nostopexec
337
+ op.props[:setip] = true
338
+ when 'throw_verification_error'
339
+ op.props[:canthrow] = true
340
+ op.props[:stopexec] = true
341
+ when 'execute_inline'
342
+ when 'iget_quick', 'iget_wide_quick', 'iget_object_quick',
343
+ 'iput_quick', 'iput_wide_quick', 'iput_object_quick'
344
+ op.props[:canthrow] = true
345
+ when 'invoke_virtual_quick', 'invoke_virtual_quick_range',
346
+ 'invoke_super_quick', 'invoke_super_quick_range',
347
+ 'invoke_direct_empty'
348
+ op.props[:canthrow] = true
349
+ op.props[:saveip] = true
350
+ op.props[:setip] = true
351
+ op.props[:stopexec] = true
352
+ when 'unused_3e', 'unused_3f', 'unused_40', 'unused_41',
353
+ 'unused_42', 'unused_43', 'unused_73', 'unused_79',
354
+ 'unused_7a', 'unused_e3', 'unused_e4', 'unused_e5',
355
+ 'unused_e6', 'unused_e7', 'unused_e8', 'unused_e9',
356
+ 'unused_ea', 'unused_eb', 'unused_ec', 'unused_ef',
357
+ 'unused_f1', 'unused_fc', 'unused_fd', 'unused_fe',
358
+ 'unused_ff'
359
+ op.props[:stopexec] = true
360
+ else
361
+ raise "Internal error #{op.name}"
362
+ end
363
+ end
364
+ end
365
+ end
366
+