metasm 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+