metasm 1.0.1 → 1.0.2
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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.hgtags +3 -0
- data/Gemfile +1 -0
- data/INSTALL +61 -0
- data/LICENCE +458 -0
- data/README +29 -21
- data/Rakefile +10 -0
- data/TODO +10 -12
- data/doc/code_organisation.txt +2 -0
- data/doc/core/DynLdr.txt +247 -0
- data/doc/core/ExeFormat.txt +43 -0
- data/doc/core/Expression.txt +220 -0
- data/doc/core/GNUExports.txt +27 -0
- data/doc/core/Ia32.txt +236 -0
- data/doc/core/SerialStruct.txt +108 -0
- data/doc/core/VirtualString.txt +145 -0
- data/doc/core/WindowsExports.txt +61 -0
- data/doc/core/index.txt +1 -0
- data/doc/style.css +6 -3
- data/doc/usage/debugger.txt +327 -0
- data/doc/usage/index.txt +1 -0
- data/doc/use_cases.txt +2 -2
- data/metasm.gemspec +22 -0
- data/{lib/metasm.rb → metasm.rb} +11 -3
- data/{lib/metasm → metasm}/compile_c.rb +13 -7
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +425 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
- data/metasm/cpu/arm/opcodes.rb +324 -0
- data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
- data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
- data/metasm/cpu/arm64.rb +15 -0
- data/metasm/cpu/arm64/debug.rb +38 -0
- data/metasm/cpu/arm64/decode.rb +289 -0
- data/metasm/cpu/arm64/encode.rb +41 -0
- data/metasm/cpu/arm64/main.rb +105 -0
- data/metasm/cpu/arm64/opcodes.rb +232 -0
- data/metasm/cpu/arm64/parse.rb +20 -0
- data/metasm/cpu/arm64/render.rb +95 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
- data/metasm/cpu/bpf/decode.rb +142 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +41 -0
- data/metasm/cpu/cy16.rb +9 -0
- data/metasm/cpu/cy16/decode.rb +253 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +41 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
- data/metasm/cpu/mips.rb +14 -0
- data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
- data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
- data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
- data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
- data/metasm/cpu/msp430/decode.rb +247 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
- data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
- data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
- data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
- data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
- data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
- data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +136 -0
- data/metasm/cpu/python/main.rb +36 -0
- data/metasm/cpu/python/opcodes.rb +180 -0
- data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
- data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
- data/metasm/cpu/x86_64/opcodes.rb +136 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +313 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +59 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
- data/{lib/metasm → metasm}/decode.rb +35 -4
- data/{lib/metasm → metasm}/decompile.rb +15 -16
- data/{lib/metasm → metasm}/disassemble.rb +201 -45
- data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
- data/{lib/metasm → metasm}/dynldr.rb +220 -133
- data/{lib/metasm → metasm}/encode.rb +10 -1
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
- data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
- data/metasm/exe_format/pyc.rb +167 -0
- data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
- data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
- data/metasm/exe_format/shellcode_rwx.rb +114 -0
- data/metasm/exe_format/swf.rb +205 -0
- data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
- data/metasm/exe_format/zip.rb +335 -0
- data/metasm/gui.rb +13 -0
- data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
- data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
- data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1695 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +93 -27
- data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
- data/{lib/metasm → metasm}/gui/qt.rb +12 -2
- data/{lib/metasm → metasm}/gui/win32.rb +179 -42
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +389 -264
- data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
- data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
- data/{lib/metasm → metasm}/os/linux.rb +628 -151
- data/metasm/os/main.rb +330 -0
- data/{lib/metasm → metasm}/os/windows.rb +132 -42
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +26 -24
- data/{lib/metasm → metasm}/parse_c.rb +221 -116
- data/{lib/metasm → metasm}/preprocessor.rb +55 -40
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +2 -1
- data/misc/lint.rb +58 -0
- data/misc/txt2html.rb +9 -7
- data/samples/bindiff.rb +3 -4
- data/samples/dasm-plugins/bindiff.rb +15 -0
- data/samples/dasm-plugins/bookmark.rb +133 -0
- data/samples/dasm-plugins/c_constants.rb +57 -0
- data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
- data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
- data/samples/dasm-plugins/dasm_all.rb +70 -0
- data/samples/dasm-plugins/demangle_cpp.rb +31 -0
- data/samples/dasm-plugins/deobfuscate.rb +251 -0
- data/samples/dasm-plugins/dump_text.rb +35 -0
- data/samples/dasm-plugins/export_graph_svg.rb +86 -0
- data/samples/dasm-plugins/findgadget.rb +75 -0
- data/samples/dasm-plugins/hl_opcode.rb +32 -0
- data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
- data/samples/dasm-plugins/imm2off.rb +34 -0
- data/samples/dasm-plugins/match_libsigs.rb +93 -0
- data/samples/dasm-plugins/patch_file.rb +95 -0
- data/samples/dasm-plugins/scanfuncstart.rb +36 -0
- data/samples/dasm-plugins/scanxrefs.rb +26 -0
- data/samples/dasm-plugins/selfmodify.rb +197 -0
- data/samples/dasm-plugins/stringsxrefs.rb +28 -0
- data/samples/dasmnavig.rb +1 -1
- data/samples/dbg-apihook.rb +24 -9
- data/samples/dbg-plugins/heapscan.rb +283 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
- data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
- data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
- data/samples/dbg-plugins/heapscan/winheap.h +174 -0
- data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
- data/samples/dbg-plugins/trace_func.rb +214 -0
- data/samples/disassemble-gui.rb +35 -5
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +12 -3
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +175 -381
- data/samples/metasm-shell.rb +1 -2
- data/samples/peldr.rb +2 -2
- data/tests/all.rb +1 -1
- data/tests/arc.rb +26 -0
- data/tests/dynldr.rb +22 -4
- data/tests/expression.rb +55 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +79 -26
- data/tests/mips.rb +9 -2
- data/tests/x86_64.rb +66 -18
- metadata +330 -218
- data/lib/metasm/arm/opcodes.rb +0 -177
- data/lib/metasm/gui.rb +0 -23
- data/lib/metasm/gui/dasm_graph.rb +0 -1354
- data/lib/metasm/ia32.rb +0 -14
- data/lib/metasm/ia32/opcodes.rb +0 -873
- data/lib/metasm/ppc/parse.rb +0 -52
- data/lib/metasm/x86_64.rb +0 -12
- data/lib/metasm/x86_64/opcodes.rb +0 -118
- data/samples/gdbclient.rb +0 -583
- data/samples/rubstop.rb +0 -399
|
File without changes
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
require 'metasm/main'
|
|
8
|
-
require 'metasm/
|
|
9
|
-
require 'metasm/
|
|
10
|
-
require 'metasm/
|
|
11
|
-
require 'metasm/
|
|
8
|
+
require 'metasm/cpu/ppc/parse'
|
|
9
|
+
require 'metasm/cpu/ppc/encode'
|
|
10
|
+
require 'metasm/cpu/ppc/decode'
|
|
11
|
+
require 'metasm/cpu/ppc/decompile'
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
require 'metasm/ppc/opcodes'
|
|
7
|
+
require 'metasm/cpu/ppc/opcodes'
|
|
8
8
|
require 'metasm/decode'
|
|
9
9
|
|
|
10
10
|
module Metasm
|
|
@@ -13,8 +13,8 @@ class PowerPC
|
|
|
13
13
|
# bit = 0 if can be mutated by an field value, 1 if fixed by opcode
|
|
14
14
|
return if not op.bin.kind_of? Integer
|
|
15
15
|
op.bin_mask = 0
|
|
16
|
-
op.
|
|
17
|
-
op.bin_mask |=
|
|
16
|
+
op.fields.each { |k, (m, s)|
|
|
17
|
+
op.bin_mask |= m << s
|
|
18
18
|
}
|
|
19
19
|
op.bin_mask = 0xffff_ffff ^ op.bin_mask
|
|
20
20
|
end
|
|
@@ -37,7 +37,7 @@ class PowerPC
|
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def decode_findopcode(edata)
|
|
40
|
-
return if edata.ptr
|
|
40
|
+
return if edata.ptr+4 > edata.length
|
|
41
41
|
di = DecodedInstruction.new(self)
|
|
42
42
|
val = edata.decode_imm(:u32, @endianness)
|
|
43
43
|
edata.ptr -= 4
|
|
@@ -67,14 +67,20 @@ class PowerPC
|
|
|
67
67
|
when :fra, :frb, :frc, :frs, :frt; FPR.new field_val[a]
|
|
68
68
|
when :ra_i16, :ra_i16s, :ra_i16q
|
|
69
69
|
i = field_val[{:ra_i16 => :d, :ra_i16s => :ds, :ra_i16q => :dq}[a]]
|
|
70
|
-
|
|
71
|
-
when :bd, :d, :ds, :dq, :si, :ui, :li, :sh, :
|
|
72
|
-
when :
|
|
70
|
+
Memref.new GPR.new(field_val[:ra]), Expression[i]
|
|
71
|
+
when :bd, :d, :ds, :dq, :si, :ui, :li, :sh, :mb, :me, :mb_, :me_, :u; Expression[field_val[a]]
|
|
72
|
+
when :ba, :bf, :bfa, :bt; CR.new field_val[a]
|
|
73
|
+
when :bb, :bh, :flm, :fxm, :l_, :l__, :lev, :nb, :sh_, :spr, :sr, :tbr, :th, :to
|
|
74
|
+
puts "PPC.decode: unsupported argument #{a.inspect}" if $VERBOSE # TODO
|
|
75
|
+
Expression[field_val[a]]
|
|
73
76
|
else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
|
|
74
77
|
end
|
|
75
78
|
}
|
|
79
|
+
|
|
76
80
|
di.bin_length += edata.ptr - before_ptr
|
|
77
81
|
|
|
82
|
+
return if edata.ptr > edata.length
|
|
83
|
+
|
|
78
84
|
decode_aliases(di.instruction)
|
|
79
85
|
|
|
80
86
|
di
|
|
@@ -84,8 +90,8 @@ class PowerPC
|
|
|
84
90
|
case i.opname
|
|
85
91
|
when /^n?or\.?$/
|
|
86
92
|
if i.args[1] == i.args[2]
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
i.args.pop
|
|
94
|
+
i.opname = {'or' => 'mr', 'or.' => 'mr.', 'nor' => 'not', 'nor.' => 'not.'}[i.opname]
|
|
89
95
|
end
|
|
90
96
|
when /^addi/
|
|
91
97
|
if a = i.args[2].reduce and a.kind_of? Integer and a < 0
|
|
@@ -107,7 +113,7 @@ class PowerPC
|
|
|
107
113
|
# else just add the offset +off+ of the instruction + its length (off may be an Expression)
|
|
108
114
|
# assumes edata.ptr points just after the instruction (as decode_instr_op left it)
|
|
109
115
|
# do not call twice on the same di !
|
|
110
|
-
|
|
116
|
+
def decode_instr_interpret(di, addr)
|
|
111
117
|
if di.opcode.props[:setip] and di.instruction.args.last.kind_of? Expression and di.opcode.name[0] != ?t and di.opcode.name[-1] != ?a
|
|
112
118
|
arg = Expression[addr, :+, di.instruction.args.last].reduce
|
|
113
119
|
di.instruction.args[-1] = Expression[arg]
|
|
@@ -191,11 +197,11 @@ class PowerPC
|
|
|
191
197
|
ptr = m.pointer.externals.grep(Symbol).first
|
|
192
198
|
ret[ptr] = m.pointer if ptr != a0
|
|
193
199
|
ret
|
|
194
|
-
|
|
200
|
+
}
|
|
195
201
|
when 'lwz'; lambda { |di, a0, m| { a0 => Expression[m] } }
|
|
196
202
|
when 'stwu'; lambda { |di, a0, m|
|
|
197
203
|
{ m => Expression[a0], m.pointer.externals.grep(Symbol).first => m.pointer }
|
|
198
|
-
|
|
204
|
+
}
|
|
199
205
|
when 'stw'; lambda { |di, a0, m| { m => Expression[a0] } }
|
|
200
206
|
when 'rlwinm'; lambda { |di, a0, a1, sh, mb, me|
|
|
201
207
|
mb, me = mb.reduce, me.reduce
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
require 'metasm/ppc/main'
|
|
7
|
+
require 'metasm/cpu/ppc/main'
|
|
8
8
|
|
|
9
9
|
module Metasm
|
|
10
10
|
class PowerPC
|
|
@@ -25,7 +25,7 @@ class PowerPC
|
|
|
25
25
|
# returns { blockaddr => [list of vars that are needed by a following block] }
|
|
26
26
|
def decompile_func_finddeps(dcmp, blocks, func)
|
|
27
27
|
deps_r = {} ; deps_w = {} ; deps_to = {}
|
|
28
|
-
deps_subfunc = {}
|
|
28
|
+
deps_subfunc = {} # things read/written by subfuncs
|
|
29
29
|
|
|
30
30
|
# find read/writes by each block
|
|
31
31
|
blocks.each { |b, to|
|
|
@@ -43,7 +43,7 @@ class PowerPC
|
|
|
43
43
|
end
|
|
44
44
|
}
|
|
45
45
|
#a << :eax if di.opcode.name == 'ret' # standard ABI
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
deps_r[b] |= a.map { |ee| Expression[ee].externals.grep(::Symbol) }.flatten - [:unknown] - deps_w[b]
|
|
48
48
|
deps_w[b] |= w.map { |ee| Expression[ee].externals.grep(::Symbol) }.flatten - [:unknown]
|
|
49
49
|
}
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
require 'metasm/ppc/opcodes'
|
|
7
|
+
require 'metasm/cpu/ppc/opcodes'
|
|
8
8
|
require 'metasm/encode'
|
|
9
9
|
|
|
10
10
|
module Metasm
|
|
@@ -31,7 +31,7 @@ class PowerPC
|
|
|
31
31
|
|
|
32
32
|
op.args.zip(instr.args).each { |sym, arg|
|
|
33
33
|
case sym
|
|
34
|
-
when :rs, :rt, :rd
|
|
34
|
+
when :rs, :rt, :rd, :ba, :bf, :bfa, :bt
|
|
35
35
|
set_field[sym, arg.i]
|
|
36
36
|
when :ft
|
|
37
37
|
set_field[sym, arg.i]
|
|
@@ -11,10 +11,15 @@ module Metasm
|
|
|
11
11
|
class PowerPC < CPU
|
|
12
12
|
class Reg
|
|
13
13
|
include Renderable
|
|
14
|
+
class << self
|
|
15
|
+
attr_accessor :s_to_i, :i_to_s
|
|
16
|
+
end
|
|
14
17
|
|
|
15
18
|
def ==(o)
|
|
16
19
|
o.class == self.class and (not respond_to?(:i) or o.i == i)
|
|
17
20
|
end
|
|
21
|
+
|
|
22
|
+
def render ; [self.class.i_to_s[@i]] ; end
|
|
18
23
|
end
|
|
19
24
|
|
|
20
25
|
# general purpose reg
|
|
@@ -24,17 +29,14 @@ class PowerPC < CPU
|
|
|
24
29
|
@i = i
|
|
25
30
|
end
|
|
26
31
|
|
|
27
|
-
|
|
28
|
-
|
|
32
|
+
@s_to_i = (0..31).inject({}) { |h, i| h.update((i == 1 ? 'sp' : "r#{i}") => i) }
|
|
33
|
+
@i_to_s = @s_to_i.invert
|
|
34
|
+
Sym = @s_to_i.sort.transpose.last
|
|
29
35
|
def symbolic ; Sym[@i] end
|
|
30
|
-
def render ; [@i == 1 ? 'sp' : "r#@i"] end
|
|
31
36
|
end
|
|
32
37
|
|
|
33
38
|
# special purpose reg
|
|
34
39
|
class SPR < Reg
|
|
35
|
-
class << self
|
|
36
|
-
attr_accessor :s_to_i, :i_to_s
|
|
37
|
-
end
|
|
38
40
|
@s_to_i = {'xer' => 1, 'lr' => 8, 'ctr' => 9, 'dec' => 22, 'srr0' => 26, 'srr1' => 27,
|
|
39
41
|
'sprg0' => 272, 'sprg1' => 273, 'sprg2' => 274, 'sprg3' => 275, 'pvr' => 287}
|
|
40
42
|
@i_to_s = @s_to_i.invert
|
|
@@ -50,14 +52,15 @@ class PowerPC < CPU
|
|
|
50
52
|
end
|
|
51
53
|
|
|
52
54
|
# floating point
|
|
53
|
-
class FPR
|
|
55
|
+
class FPR < Reg
|
|
54
56
|
attr_accessor :i
|
|
55
57
|
def initialize(i)
|
|
56
58
|
@i = i
|
|
57
59
|
end
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
@s_to_i = (0..31).inject({}) { |h, i| h.update "fp#{i}" => i }
|
|
62
|
+
@i_to_s = @s_to_i.invert
|
|
63
|
+
Sym = @s_to_i.sort.transpose.last
|
|
61
64
|
end
|
|
62
65
|
|
|
63
66
|
# machine state reg
|
|
@@ -73,8 +76,10 @@ class PowerPC < CPU
|
|
|
73
76
|
@i = i
|
|
74
77
|
end
|
|
75
78
|
|
|
79
|
+
@s_to_i = (0..31).inject({}) { |h, i| h.update "cr#{i}" => i }
|
|
80
|
+
@i_to_s = @s_to_i.invert
|
|
81
|
+
Sym = @s_to_i.sort.transpose.last
|
|
76
82
|
def symbolic ; "cr#@i".to_sym end
|
|
77
|
-
def render ; ["cr#@i"] end
|
|
78
83
|
end
|
|
79
84
|
|
|
80
85
|
# indirection : reg+reg or reg+16b_off
|
|
@@ -89,13 +94,13 @@ class PowerPC < CPU
|
|
|
89
94
|
b = @base.symbolic
|
|
90
95
|
b = nil if b == :r0 # XXX is it true ?
|
|
91
96
|
o = @offset
|
|
92
|
-
o = o.symbolic if o.kind_of?
|
|
97
|
+
o = o.symbolic if o.kind_of?(Reg)
|
|
93
98
|
Indirection[Expression[b, :+, o].reduce, 4, orig]
|
|
94
99
|
end
|
|
95
100
|
|
|
96
101
|
include Renderable
|
|
97
102
|
def render
|
|
98
|
-
if @offset.kind_of?
|
|
103
|
+
if @offset.kind_of?(Reg)
|
|
99
104
|
['(', @base, ' + ', @offset, ')']
|
|
100
105
|
else
|
|
101
106
|
[@offset, '(', @base, ')']
|
|
@@ -4,14 +4,17 @@
|
|
|
4
4
|
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
require 'metasm/ppc/main'
|
|
7
|
+
require 'metasm/cpu/ppc/main'
|
|
8
8
|
|
|
9
9
|
module Metasm
|
|
10
10
|
class PowerPC
|
|
11
11
|
def addop(name, bin, *argprops)
|
|
12
|
-
o = Opcode.new name, bin
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
o = Opcode.new name, bin
|
|
13
|
+
argprops.each { |a|
|
|
14
|
+
o.args << a if @valid_args[a]
|
|
15
|
+
o.fields[a] = [@fields_mask[a], @fields_shift[a]] if @fields_mask[a]
|
|
16
|
+
o.props[a] = true if @valid_props[a]
|
|
17
|
+
}
|
|
15
18
|
@opcode_list << o
|
|
16
19
|
end
|
|
17
20
|
|
|
@@ -113,6 +116,9 @@ class PowerPC
|
|
|
113
116
|
:tbr => 0x3FF, :th => 15, :to => 31, :u => 15, :ui => 0xFFFF,
|
|
114
117
|
:ign_bo_zzz => 0b101111111, :ign_bo_z => 1, :ign_bo_at => 3, :ign_bo_at2 => 0b100111111
|
|
115
118
|
|
|
119
|
+
@valid_args = @fields_mask.dup
|
|
120
|
+
[:ign_bo_zzz, :ign_bo_z, :ign_bo_at, :ign_bo_at2, :aa, :lk, :oe, :rc, :l].each { |k| @valid_args.delete k }
|
|
121
|
+
|
|
116
122
|
@fields_shift[:ra_i16] = @fields_shift[:ra_i16s] = @fields_shift[:ra_i16q] = 0
|
|
117
123
|
@fields_mask[:ra_i16] = (@fields_mask[:d] << @fields_shift[:d]) | (@fields_mask[:ra] << @fields_shift[:ra])
|
|
118
124
|
@fields_mask[:ra_i16s] = (@fields_mask[:ds] << @fields_shift[:d]) | (@fields_mask[:ra] << @fields_shift[:ra])
|
|
@@ -123,7 +129,7 @@ class PowerPC
|
|
|
123
129
|
addop_branchcond 'b', 0x40000000, :bd
|
|
124
130
|
addop_branchcond 'b', 0x4C000020, :lr
|
|
125
131
|
addop_branchcond 'b', 0x4C000420, :ctr
|
|
126
|
-
|
|
132
|
+
|
|
127
133
|
addop 'sc', 0x44000002, :lev
|
|
128
134
|
addop 'crand', 0x4C000202, :bt, :ba, :bb
|
|
129
135
|
addop 'crxor', 0x4C000182, :bt, :ba, :bb
|
|
@@ -0,0 +1,55 @@
|
|
|
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/cpu/ppc/opcodes'
|
|
8
|
+
require 'metasm/parse'
|
|
9
|
+
|
|
10
|
+
module Metasm
|
|
11
|
+
class PowerPC
|
|
12
|
+
# TODO
|
|
13
|
+
def parse_arg_valid?(op, sym, arg)
|
|
14
|
+
case sym
|
|
15
|
+
when :ra, :rb, :rs, :rt; arg.kind_of?(GPR)
|
|
16
|
+
when :fra, :frb, :frc, :frs, :frt; arg.kind_of?(FPR)
|
|
17
|
+
when :ra_i16, :ra_i16s, :ra_i16q; arg.kind_of?(Memref)
|
|
18
|
+
when :bd, :d, :ds, :dq, :si, :ui, :li, :sh, :mb, :me, :mb_, :me_, :u; arg.kind_of?(Expression)
|
|
19
|
+
when :ba, :bf, :bfa, :bt; arg.kind_of?(CR)
|
|
20
|
+
when :ign_bo_zzz, :ign_bo_z, :ign_bo_at, :ign_bo_at2, :aa, :lk, :oe, :rc, :l; # ?
|
|
21
|
+
when :bb, :bh, :flm, :fxm, :l_, :l__, :lev, :nb, :sh_, :spr, :sr, :tbr, :th, :to
|
|
22
|
+
# TODO
|
|
23
|
+
else raise "internal error: mips arg #{sym.inspect}"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def parse_argument(pgm)
|
|
28
|
+
pgm.skip_space
|
|
29
|
+
return if not tok = pgm.readtok
|
|
30
|
+
if tok.type == :string
|
|
31
|
+
return GPR.new(GPR.s_to_i[tok.raw]) if GPR.s_to_i[tok.raw]
|
|
32
|
+
return SPR.new(SPR.s_to_i[tok.raw]) if SPR.s_to_i[tok.raw]
|
|
33
|
+
return FPR.new(FPR.s_to_i[tok.raw]) if FPR.s_to_i[tok.raw]
|
|
34
|
+
return CR.new(CR.s_to_i[tok.raw]) if CR.s_to_i[tok.raw]
|
|
35
|
+
return MSR.new if tok.raw == 'msr'
|
|
36
|
+
end
|
|
37
|
+
pgm.unreadtok tok
|
|
38
|
+
arg = Expression.parse pgm
|
|
39
|
+
pgm.skip_space
|
|
40
|
+
# check memory indirection: 'off(base reg)' # XXX scaled index ?
|
|
41
|
+
if arg and pgm.nexttok and pgm.nexttok.type == :punct and pgm.nexttok.raw == '('
|
|
42
|
+
pgm.readtok
|
|
43
|
+
pgm.skip_space_eol
|
|
44
|
+
ntok = pgm.readtok
|
|
45
|
+
raise tok, "Invalid base #{ntok}" unless ntok and ntok.type == :string and GPR.s_to_i[ntok.raw]
|
|
46
|
+
base = GPR.new GPR.s_to_i[ntok.raw]
|
|
47
|
+
pgm.skip_space_eol
|
|
48
|
+
ntok = pgm.readtok
|
|
49
|
+
raise tok, "Invalid memory reference, ')' expected" if not ntok or ntok.type != :punct or ntok.raw != ')'
|
|
50
|
+
arg = Memref.new base, arg
|
|
51
|
+
end
|
|
52
|
+
arg
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
2
|
+
# Copyright (C) 2006-2010 Yoann GUILLOT
|
|
3
|
+
#
|
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
|
+
|
|
6
|
+
require 'metasm/cpu/python/opcodes'
|
|
7
|
+
require 'metasm/decode'
|
|
8
|
+
|
|
9
|
+
module Metasm
|
|
10
|
+
class Python
|
|
11
|
+
def build_bin_lookaside
|
|
12
|
+
opcode_list.inject({}) { |la, op| la.update op.bin => op }
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def decode_findopcode(edata)
|
|
16
|
+
di = DecodedInstruction.new(self)
|
|
17
|
+
|
|
18
|
+
byte = edata.decode_imm(:u8, :little)
|
|
19
|
+
|
|
20
|
+
di if di.opcode = @bin_lookaside[byte]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def decode_instr_op(edata, di)
|
|
24
|
+
di.bin_length = 1
|
|
25
|
+
|
|
26
|
+
di.instruction.opname = di.opcode.name
|
|
27
|
+
|
|
28
|
+
di.opcode.args.each { |a|
|
|
29
|
+
case a
|
|
30
|
+
when :cmp
|
|
31
|
+
di.bin_length += 2
|
|
32
|
+
v = edata.decode_imm(:i16, @endianness)
|
|
33
|
+
di.instruction.args << (CMP_OP[v] || Expression[v])
|
|
34
|
+
when :i16
|
|
35
|
+
di.bin_length += 2
|
|
36
|
+
di.instruction.args << Expression[edata.decode_imm(:i16, @endianness)]
|
|
37
|
+
when :u8
|
|
38
|
+
di.bin_length += 1
|
|
39
|
+
di.instruction.args << Expression[edata.decode_imm(:u8, @endianness)]
|
|
40
|
+
else
|
|
41
|
+
raise "unsupported arg #{a.inspect}"
|
|
42
|
+
end
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return if edata.ptr > edata.length
|
|
46
|
+
|
|
47
|
+
di
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def decode_instr_interpret(di, addr)
|
|
51
|
+
case di.opcode.name
|
|
52
|
+
when 'LOAD_CONST'
|
|
53
|
+
if c = prog_code(addr)
|
|
54
|
+
cst = c[:consts][di.instruction.args.first.reduce]
|
|
55
|
+
if cst.kind_of? Hash and cst[:type] == :code
|
|
56
|
+
di.add_comment "lambda #{Expression[cst[:fileoff]]}"
|
|
57
|
+
else
|
|
58
|
+
di.add_comment cst.inspect
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
when 'LOAD_NAME', 'LOAD_ATTR', 'LOAD_GLOBAL', 'STORE_NAME', 'IMPORT_NAME', 'LOAD_FAST'
|
|
62
|
+
if c = prog_code(addr)
|
|
63
|
+
di.add_comment c[:names][di.instruction.args.first.reduce].inspect
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
di
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def backtrace_binding
|
|
70
|
+
@backtrace_binding ||= init_backtrace_binding
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def init_backtrace_binding
|
|
74
|
+
@backtrace_binding ||= {}
|
|
75
|
+
|
|
76
|
+
opcode_list.each { |op|
|
|
77
|
+
binding = case op
|
|
78
|
+
when 'nop'; lambda { |*a| {} }
|
|
79
|
+
end
|
|
80
|
+
@backtrace_binding[op] ||= binding if binding
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@backtrace_binding
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def get_backtrace_binding(di)
|
|
87
|
+
a = di.instruction.args.map { |arg|
|
|
88
|
+
case arg
|
|
89
|
+
when Var; arg.symbolic
|
|
90
|
+
else arg
|
|
91
|
+
end
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if binding = backtrace_binding[di.opcode.basename]
|
|
95
|
+
binding[di, *a]
|
|
96
|
+
else
|
|
97
|
+
puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
|
|
98
|
+
{ :incomplete_binding => Expression[1] }
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def get_xrefs_x(dasm, di)
|
|
103
|
+
return [] if not di.opcode.props[:setip]
|
|
104
|
+
|
|
105
|
+
arg = case di.opcode.name
|
|
106
|
+
when 'JUMP_FORWARD', 'FOR_ITER'
|
|
107
|
+
# relative offset
|
|
108
|
+
di.instruction.args.last.reduce + di.next_addr
|
|
109
|
+
when 'CALL_FUNCTION_VAR'
|
|
110
|
+
'lol'
|
|
111
|
+
when /CALL/
|
|
112
|
+
:unknown
|
|
113
|
+
else
|
|
114
|
+
# absolute offset from :code start
|
|
115
|
+
off = di.instruction.args.last.reduce
|
|
116
|
+
if c = prog_code(di)
|
|
117
|
+
off += c[:fileoff]
|
|
118
|
+
end
|
|
119
|
+
off
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
[Expression[(arg.kind_of?(Var) ? arg.symbolic : arg)]]
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def prog_code(addr)
|
|
126
|
+
addr = addr.address if addr.kind_of? DecodedInstruction
|
|
127
|
+
@last_prog_code ||= nil
|
|
128
|
+
return @last_prog_code if @last_prog_code and @last_prog_code[:fileoff] <= addr and @last_prog_code[:fileoff] + @last_prog_code[:code].length > addr
|
|
129
|
+
@last_prog_code = @program.code_at_off(addr) if @program
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def backtrace_is_function_return(expr, di=nil)
|
|
133
|
+
#Expression[expr].reduce == Expression['wtf']
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
end
|