metasm 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|