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.
- data/BUGS +11 -0
- data/CREDITS +17 -0
- data/README +270 -0
- data/TODO +114 -0
- data/doc/code_organisation.txt +146 -0
- data/doc/const_missing.txt +16 -0
- data/doc/core_classes.txt +75 -0
- data/doc/feature_list.txt +53 -0
- data/doc/index.txt +59 -0
- data/doc/install_notes.txt +170 -0
- data/doc/style.css +3 -0
- data/doc/use_cases.txt +18 -0
- data/lib/metasm.rb +80 -0
- data/lib/metasm/arm.rb +12 -0
- data/lib/metasm/arm/debug.rb +39 -0
- data/lib/metasm/arm/decode.rb +167 -0
- data/lib/metasm/arm/encode.rb +77 -0
- data/lib/metasm/arm/main.rb +75 -0
- data/lib/metasm/arm/opcodes.rb +177 -0
- data/lib/metasm/arm/parse.rb +130 -0
- data/lib/metasm/arm/render.rb +55 -0
- data/lib/metasm/compile_c.rb +1457 -0
- data/lib/metasm/dalvik.rb +8 -0
- data/lib/metasm/dalvik/decode.rb +196 -0
- data/lib/metasm/dalvik/main.rb +60 -0
- data/lib/metasm/dalvik/opcodes.rb +366 -0
- data/lib/metasm/decode.rb +213 -0
- data/lib/metasm/decompile.rb +2659 -0
- data/lib/metasm/disassemble.rb +2068 -0
- data/lib/metasm/disassemble_api.rb +1280 -0
- data/lib/metasm/dynldr.rb +1329 -0
- data/lib/metasm/encode.rb +333 -0
- data/lib/metasm/exe_format/a_out.rb +194 -0
- data/lib/metasm/exe_format/autoexe.rb +82 -0
- data/lib/metasm/exe_format/bflt.rb +189 -0
- data/lib/metasm/exe_format/coff.rb +455 -0
- data/lib/metasm/exe_format/coff_decode.rb +901 -0
- data/lib/metasm/exe_format/coff_encode.rb +1078 -0
- data/lib/metasm/exe_format/dex.rb +457 -0
- data/lib/metasm/exe_format/dol.rb +145 -0
- data/lib/metasm/exe_format/elf.rb +923 -0
- data/lib/metasm/exe_format/elf_decode.rb +979 -0
- data/lib/metasm/exe_format/elf_encode.rb +1375 -0
- data/lib/metasm/exe_format/macho.rb +827 -0
- data/lib/metasm/exe_format/main.rb +228 -0
- data/lib/metasm/exe_format/mz.rb +164 -0
- data/lib/metasm/exe_format/nds.rb +172 -0
- data/lib/metasm/exe_format/pe.rb +437 -0
- data/lib/metasm/exe_format/serialstruct.rb +246 -0
- data/lib/metasm/exe_format/shellcode.rb +114 -0
- data/lib/metasm/exe_format/xcoff.rb +167 -0
- data/lib/metasm/gui.rb +23 -0
- data/lib/metasm/gui/cstruct.rb +373 -0
- data/lib/metasm/gui/dasm_coverage.rb +199 -0
- data/lib/metasm/gui/dasm_decomp.rb +369 -0
- data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
- data/lib/metasm/gui/dasm_graph.rb +1354 -0
- data/lib/metasm/gui/dasm_hex.rb +543 -0
- data/lib/metasm/gui/dasm_listing.rb +599 -0
- data/lib/metasm/gui/dasm_main.rb +906 -0
- data/lib/metasm/gui/dasm_opcodes.rb +291 -0
- data/lib/metasm/gui/debug.rb +1228 -0
- data/lib/metasm/gui/gtk.rb +884 -0
- data/lib/metasm/gui/qt.rb +495 -0
- data/lib/metasm/gui/win32.rb +3004 -0
- data/lib/metasm/gui/x11.rb +621 -0
- data/lib/metasm/ia32.rb +14 -0
- data/lib/metasm/ia32/compile_c.rb +1523 -0
- data/lib/metasm/ia32/debug.rb +193 -0
- data/lib/metasm/ia32/decode.rb +1167 -0
- data/lib/metasm/ia32/decompile.rb +564 -0
- data/lib/metasm/ia32/encode.rb +314 -0
- data/lib/metasm/ia32/main.rb +233 -0
- data/lib/metasm/ia32/opcodes.rb +872 -0
- data/lib/metasm/ia32/parse.rb +327 -0
- data/lib/metasm/ia32/render.rb +91 -0
- data/lib/metasm/main.rb +1193 -0
- data/lib/metasm/mips.rb +11 -0
- data/lib/metasm/mips/compile_c.rb +7 -0
- data/lib/metasm/mips/decode.rb +253 -0
- data/lib/metasm/mips/encode.rb +51 -0
- data/lib/metasm/mips/main.rb +72 -0
- data/lib/metasm/mips/opcodes.rb +443 -0
- data/lib/metasm/mips/parse.rb +51 -0
- data/lib/metasm/mips/render.rb +43 -0
- data/lib/metasm/os/gnu_exports.rb +270 -0
- data/lib/metasm/os/linux.rb +1112 -0
- data/lib/metasm/os/main.rb +1686 -0
- data/lib/metasm/os/remote.rb +527 -0
- data/lib/metasm/os/windows.rb +2027 -0
- data/lib/metasm/os/windows_exports.rb +745 -0
- data/lib/metasm/parse.rb +876 -0
- data/lib/metasm/parse_c.rb +3938 -0
- data/lib/metasm/pic16c/decode.rb +42 -0
- data/lib/metasm/pic16c/main.rb +17 -0
- data/lib/metasm/pic16c/opcodes.rb +68 -0
- data/lib/metasm/ppc.rb +11 -0
- data/lib/metasm/ppc/decode.rb +264 -0
- data/lib/metasm/ppc/decompile.rb +251 -0
- data/lib/metasm/ppc/encode.rb +51 -0
- data/lib/metasm/ppc/main.rb +129 -0
- data/lib/metasm/ppc/opcodes.rb +410 -0
- data/lib/metasm/ppc/parse.rb +52 -0
- data/lib/metasm/preprocessor.rb +1277 -0
- data/lib/metasm/render.rb +130 -0
- data/lib/metasm/sh4.rb +8 -0
- data/lib/metasm/sh4/decode.rb +336 -0
- data/lib/metasm/sh4/main.rb +292 -0
- data/lib/metasm/sh4/opcodes.rb +381 -0
- data/lib/metasm/x86_64.rb +12 -0
- data/lib/metasm/x86_64/compile_c.rb +1025 -0
- data/lib/metasm/x86_64/debug.rb +59 -0
- data/lib/metasm/x86_64/decode.rb +268 -0
- data/lib/metasm/x86_64/encode.rb +264 -0
- data/lib/metasm/x86_64/main.rb +135 -0
- data/lib/metasm/x86_64/opcodes.rb +118 -0
- data/lib/metasm/x86_64/parse.rb +68 -0
- data/misc/bottleneck.rb +61 -0
- data/misc/cheader-findpppath.rb +58 -0
- data/misc/hexdiff.rb +74 -0
- data/misc/hexdump.rb +55 -0
- data/misc/metasm-all.rb +13 -0
- data/misc/objdiff.rb +47 -0
- data/misc/objscan.rb +40 -0
- data/misc/pdfparse.rb +661 -0
- data/misc/ppc_pdf2oplist.rb +192 -0
- data/misc/tcp_proxy_hex.rb +84 -0
- data/misc/txt2html.rb +440 -0
- data/samples/a.out.rb +31 -0
- data/samples/asmsyntax.rb +77 -0
- data/samples/bindiff.rb +555 -0
- data/samples/compilation-steps.rb +49 -0
- data/samples/cparser_makestackoffset.rb +55 -0
- data/samples/dasm-backtrack.rb +38 -0
- data/samples/dasmnavig.rb +318 -0
- data/samples/dbg-apihook.rb +228 -0
- data/samples/dbghelp.rb +143 -0
- data/samples/disassemble-gui.rb +102 -0
- data/samples/disassemble.rb +133 -0
- data/samples/dump_upx.rb +95 -0
- data/samples/dynamic_ruby.rb +1929 -0
- data/samples/elf_list_needed.rb +46 -0
- data/samples/elf_listexports.rb +33 -0
- data/samples/elfencode.rb +25 -0
- data/samples/exeencode.rb +128 -0
- data/samples/factorize-headers-elfimports.rb +77 -0
- data/samples/factorize-headers-peimports.rb +109 -0
- data/samples/factorize-headers.rb +43 -0
- data/samples/gdbclient.rb +583 -0
- data/samples/generate_libsigs.rb +102 -0
- data/samples/hotfix_gtk_dbg.rb +59 -0
- data/samples/install_win_env.rb +78 -0
- data/samples/lindebug.rb +924 -0
- data/samples/linux_injectsyscall.rb +95 -0
- data/samples/machoencode.rb +31 -0
- data/samples/metasm-shell.rb +91 -0
- data/samples/pe-hook.rb +69 -0
- data/samples/pe-ia32-cpuid.rb +203 -0
- data/samples/pe-mips.rb +35 -0
- data/samples/pe-shutdown.rb +78 -0
- data/samples/pe-testrelocs.rb +51 -0
- data/samples/pe-testrsrc.rb +24 -0
- data/samples/pe_listexports.rb +31 -0
- data/samples/peencode.rb +19 -0
- data/samples/peldr.rb +494 -0
- data/samples/preprocess-flatten.rb +19 -0
- data/samples/r0trace.rb +308 -0
- data/samples/rubstop.rb +399 -0
- data/samples/scan_pt_gnu_stack.rb +54 -0
- data/samples/scanpeexports.rb +62 -0
- data/samples/shellcode-c.rb +40 -0
- data/samples/shellcode-dynlink.rb +146 -0
- data/samples/source.asm +34 -0
- data/samples/struct_offset.rb +47 -0
- data/samples/testpe.rb +32 -0
- data/samples/testraw.rb +45 -0
- data/samples/win32genloader.rb +132 -0
- data/samples/win32hooker-advanced.rb +169 -0
- data/samples/win32hooker.rb +96 -0
- data/samples/win32livedasm.rb +33 -0
- data/samples/win32remotescan.rb +133 -0
- data/samples/wintrace.rb +92 -0
- data/tests/all.rb +8 -0
- data/tests/dasm.rb +39 -0
- data/tests/dynldr.rb +35 -0
- data/tests/encodeddata.rb +132 -0
- data/tests/ia32.rb +82 -0
- data/tests/mips.rb +116 -0
- data/tests/parse_c.rb +239 -0
- data/tests/preprocessor.rb +269 -0
- data/tests/x86_64.rb +62 -0
- metadata +255 -0
|
@@ -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
|
+
|