metasm 1.0.0 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +3 -0
- data/.gitignore +3 -0
- data/.hgtags +3 -0
- data/Gemfile +3 -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 +3 -1
- 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 +23 -0
- data/{lib/metasm.rb → metasm.rb} +15 -3
- data/{lib/metasm → metasm}/compile_c.rb +15 -9
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +404 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/metasm/cpu/arm.rb +14 -0
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +15 -18
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +3 -6
- 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 +285 -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/mips/compile_c.rb → metasm/cpu/bpf.rb} +4 -2
- data/metasm/cpu/bpf/decode.rb +110 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +30 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/cy16.rb} +2 -4
- data/metasm/cpu/cy16/decode.rb +247 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +30 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +34 -34
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +71 -4
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +21 -12
- data/{lib/metasm/mips.rb → metasm/cpu/ebpf.rb} +3 -4
- data/metasm/cpu/ebpf/debug.rb +61 -0
- data/metasm/cpu/ebpf/decode.rb +142 -0
- data/metasm/cpu/ebpf/main.rb +58 -0
- data/metasm/cpu/ebpf/opcodes.rb +97 -0
- data/metasm/cpu/ebpf/render.rb +36 -0
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +23 -9
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +44 -6
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +342 -128
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +75 -53
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +66 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +55 -17
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +32 -5
- data/metasm/cpu/mcs51.rb +8 -0
- data/metasm/cpu/mcs51/decode.rb +99 -0
- data/metasm/cpu/mcs51/main.rb +87 -0
- data/metasm/cpu/mcs51/opcodes.rb +120 -0
- data/metasm/cpu/mips.rb +14 -0
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +59 -38
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +13 -6
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +87 -18
- 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 +243 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/metasm/cpu/openrisc.rb +11 -0
- data/metasm/cpu/openrisc/debug.rb +106 -0
- data/metasm/cpu/openrisc/decode.rb +182 -0
- data/metasm/cpu/openrisc/decompile.rb +350 -0
- data/metasm/cpu/openrisc/main.rb +70 -0
- data/metasm/cpu/openrisc/opcodes.rb +109 -0
- data/metasm/cpu/openrisc/render.rb +37 -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/metasm/cpu/ppc.rb +11 -0
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -37
- 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 +23 -18
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -6
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +116 -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 +50 -23
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +38 -27
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/st20.rb +9 -0
- data/metasm/cpu/st20/decode.rb +173 -0
- data/metasm/cpu/st20/decompile.rb +283 -0
- data/metasm/cpu/st20/main.rb +37 -0
- data/metasm/cpu/st20/opcodes.rb +140 -0
- data/{lib/metasm/arm.rb → metasm/cpu/webasm.rb} +4 -5
- data/metasm/cpu/webasm/debug.rb +31 -0
- data/metasm/cpu/webasm/decode.rb +321 -0
- data/metasm/cpu/webasm/decompile.rb +386 -0
- data/metasm/cpu/webasm/encode.rb +104 -0
- data/metasm/cpu/webasm/main.rb +81 -0
- data/metasm/cpu/webasm/opcodes.rb +214 -0
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +40 -25
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +58 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +59 -28
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +18 -6
- data/metasm/cpu/x86_64/opcodes.rb +138 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +12 -4
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +286 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +48 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +201 -407
- data/{lib/metasm → metasm}/decode.rb +104 -24
- data/{lib/metasm → metasm}/decompile.rb +804 -478
- data/{lib/metasm → metasm}/disassemble.rb +385 -170
- data/{lib/metasm → metasm}/disassemble_api.rb +684 -105
- data/{lib/metasm → metasm}/dynldr.rb +231 -138
- data/{lib/metasm → metasm}/encode.rb +20 -5
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +3 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +35 -7
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +70 -23
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +24 -22
- data/{lib/metasm → metasm}/exe_format/dex.rb +26 -8
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +108 -58
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +202 -36
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +126 -32
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +218 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +28 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +2 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +96 -11
- 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/metasm/exe_format/wasm.rb +402 -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 +177 -114
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1754 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +16 -12
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +360 -77
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +109 -34
- data/{lib/metasm → metasm}/gui/gtk.rb +174 -44
- data/{lib/metasm → metasm}/gui/qt.rb +14 -4
- data/{lib/metasm → metasm}/gui/win32.rb +180 -43
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +421 -286
- data/metasm/os/emulator.rb +175 -0
- 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 +335 -0
- data/{lib/metasm → metasm}/os/windows.rb +151 -58
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +49 -36
- data/{lib/metasm → metasm}/parse_c.rb +405 -246
- data/{lib/metasm → metasm}/preprocessor.rb +71 -41
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +4 -3
- data/misc/lint.rb +58 -0
- data/misc/objdiff.rb +4 -1
- data/misc/objscan.rb +1 -1
- data/misc/openrisc-parser.rb +79 -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 +29 -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 +48 -7
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +35 -27
- data/samples/elfencode.rb +15 -0
- data/samples/emubios.rb +251 -0
- data/samples/emudbg.rb +127 -0
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +186 -391
- data/samples/metasm-shell.rb +68 -57
- 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 +57 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +80 -26
- data/tests/mcs51.rb +27 -0
- data/tests/mips.rb +10 -3
- data/tests/preprocessor.rb +18 -0
- data/tests/x86_64.rb +66 -18
- metadata +465 -219
- metadata.gz.sig +2 -0
- 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 -872
- 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
@@ -0,0 +1,37 @@
|
|
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 ST20 < CPU
|
11
|
+
def initialize(size=32)
|
12
|
+
super()
|
13
|
+
@endianness = :little
|
14
|
+
@size = size
|
15
|
+
init_opcodes
|
16
|
+
end
|
17
|
+
|
18
|
+
def register_symbols
|
19
|
+
[:a, :b, :c]
|
20
|
+
end
|
21
|
+
|
22
|
+
def render_instruction(i)
|
23
|
+
r = []
|
24
|
+
r << i.opname
|
25
|
+
if not i.args.empty?
|
26
|
+
r << ' '
|
27
|
+
i.args.each { |a_| r << a_ << ', ' }
|
28
|
+
r.pop
|
29
|
+
end
|
30
|
+
r
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class TransPuter < ST20
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,140 @@
|
|
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/cpu/st20/main'
|
7
|
+
|
8
|
+
module Metasm
|
9
|
+
|
10
|
+
class ST20
|
11
|
+
def init_opcodes
|
12
|
+
@op_function = op_get_function
|
13
|
+
@op_operate = op_get_operate
|
14
|
+
@opcode_list = @op_function.sort.map { |b, n|
|
15
|
+
op = Opcode.new(n, b)
|
16
|
+
op.props[:setip] = true if n == 'cj'
|
17
|
+
op.props[:setip] = op.props[:stopexec] = true if n == 'j'
|
18
|
+
op.props[:setip] = op.props[:stopexec] = op.props[:saveip] = true if n == 'fcall'
|
19
|
+
op
|
20
|
+
}
|
21
|
+
@opc_operate = {}
|
22
|
+
op = Opcode.new('ret', 0)
|
23
|
+
op.props[:setip] = op.props[:stopexec] = true
|
24
|
+
@opc_operate['ret'] = op
|
25
|
+
end
|
26
|
+
|
27
|
+
def op_get_function
|
28
|
+
{
|
29
|
+
0x00 => 'j', 0x10 => 'ldlp', 0x20 => 'pfix', 0x30 => 'ldnl',
|
30
|
+
0x40 => 'ldc', 0x50 => 'ldnlp', 0x60 => 'nfix', 0x70 => 'ldl',
|
31
|
+
0x80 => 'adc', 0x90 => 'fcall', 0xa0 => 'cj', 0xb0 => 'ajw',
|
32
|
+
0xc0 => 'eqc', 0xd0 => 'stl', 0xe0 => 'stnl', 0xf0 => 'opr'
|
33
|
+
}
|
34
|
+
end
|
35
|
+
|
36
|
+
def op_get_operate
|
37
|
+
{
|
38
|
+
0x00 => 'rev', 0x01 => 'dup', 0x02 => 'rot', 0x03 => 'arot',
|
39
|
+
0x04 => 'add', 0x05 => 'sub', 0x06 => 'mul', 0x07 => 'wsub',
|
40
|
+
0x08 => 'not', 0x09 => 'and', 0x0A => 'or', 0x0B => 'shl',
|
41
|
+
0x0C => 'shr', 0x0D => 'jab', 0x0E => 'timeslice', 0x0F => 'breakpoint',
|
42
|
+
0x10 => 'addc', 0x11 => 'subc', 0x12 => 'mac', 0x13 => 'umac',
|
43
|
+
0x14 => 'smul', 0x15 => 'smacinit', 0x16 => 'smacloop', 0x17 => 'biquad',
|
44
|
+
0x18 => 'divstep', 0x19 => 'unsign', 0x1A => 'saturate', 0x1B => 'gt',
|
45
|
+
0x1C => 'gtu', 0x1D => 'order', 0x1E => 'orderu', 0x1F => 'ashr',
|
46
|
+
0x20 => 'xor', 0x21 => 'xbword', 0x22 => 'xsword', 0x23 => 'bitld',
|
47
|
+
0x24 => 'bitst', 0x25 => 'bitmask', 0x26 => 'statusset', 0x27 => 'statusclr',
|
48
|
+
0x28 => 'statustst', 0x29 => 'rmw', 0x2A => 'lbinc', 0x2B => 'sbinc',
|
49
|
+
0x2C => 'lsinc', 0x2D => 'lsxinc', 0x2E => 'ssinc', 0x2F => 'lwinc',
|
50
|
+
0x30 => 'swinc', 0x31 => 'ecall', 0x32 => 'eret', 0x33 => 'run',
|
51
|
+
0x34 => 'stop', 0x35 => 'signal', 0x36 => 'wait', 0x37 => 'enqueue',
|
52
|
+
0x38 => 'dequeue', 0x39 => 'ldtdesc', 0x3A => 'ldpi', 0x3B => 'gajw',
|
53
|
+
0x3C => 'ldprodid', 0x3D => 'io', 0x3E => 'swap32', 0x3F => 'nop',
|
54
|
+
}
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
class TransPuter
|
59
|
+
def op_get_operate
|
60
|
+
{
|
61
|
+
0x00 => 'rev', 0x01 => 'lb', 0x02 => 'bsub', 0x03 => 'endp',
|
62
|
+
0x04 => 'diff', 0x05 => 'add', 0x06 => 'gcall', 0x07 => 'in',
|
63
|
+
0x08 => 'prod', 0x09 => 'gt', 0x0a => 'wsub', 0x0b => 'out',
|
64
|
+
0x0c => 'sub', 0x0d => 'startp', 0x0e => 'outbyte', 0x0f => 'outword',
|
65
|
+
0x10 => 'seterr', 0x11 => 'mreleasep', 0x12 => 'resetch', 0x13 => 'csub0',
|
66
|
+
0x14 => 'extvrfy', 0x15 => 'stopp', 0x16 => 'ladd', 0x17 => 'stlb',
|
67
|
+
0x18 => 'sthf', 0x19 => 'norm', 0x1a => 'ldiv', 0x1b => 'ldpi',
|
68
|
+
0x1c => 'stlf', 0x1d => 'xdble', 0x1e => 'ldpri', 0x1f => 'rem',
|
69
|
+
0x20 => 'ret', 0x21 => 'lend', 0x22 => 'ldtimer', 0x23 => 'testlds',
|
70
|
+
0x24 => 'testlde', 0x25 => 'testldd', 0x26 => 'teststs', 0x27 => 'testste',
|
71
|
+
0x28 => 'teststd', 0x29 => 'testerr', 0x2a => 'testpranal', 0x2b => 'tin',
|
72
|
+
0x2c => 'div', 0x2d => 'testhardchan', 0x2e => 'dist', 0x2f => 'disc',
|
73
|
+
0x30 => 'diss', 0x31 => 'lmul', 0x32 => 'not', 0x33 => 'xor',
|
74
|
+
0x34 => 'bcnt', 0x35 => 'lshr', 0x36 => 'lshl', 0x37 => 'lsum',
|
75
|
+
0x38 => 'lsub', 0x39 => 'runp', 0x3a => 'xword', 0x3b => 'sb',
|
76
|
+
0x3c => 'gajw', 0x3d => 'savel', 0x3e => 'saveh', 0x3f => 'wcnt',
|
77
|
+
0x40 => 'shr', 0x41 => 'shl', 0x42 => 'mint', 0x43 => 'alt',
|
78
|
+
0x44 => 'altwt', 0x45 => 'altend', 0x46 => 'and', 0x47 => 'enbt',
|
79
|
+
0x48 => 'enbc', 0x49 => 'enbs', 0x4a => 'move', 0x4b => 'or',
|
80
|
+
0x4c => 'csngl', 0x4d => 'ccnt1', 0x4e => 'talt', 0x4f => 'ldiff',
|
81
|
+
0x50 => 'sthb', 0x51 => 'taltwt', 0x52 => 'sum', 0x53 => 'mul',
|
82
|
+
0x54 => 'sttimer', 0x55 => 'stoperr', 0x56 => 'cword', 0x57 => 'clrhalterr',
|
83
|
+
0x58 => 'sethalterr', 0x59 => 'testhalterr', 0x5a => 'dup', 0x5b => 'move2dinit',
|
84
|
+
0x5c => 'move2dall', 0x5d => 'move2dnonzero', 0x5e => 'move2dzero', 0x5f => 'gtu',
|
85
|
+
0x60 => 'extin', 0x61 => 'extout', 0x62 => 'minn', 0x63 => 'unpacksn',
|
86
|
+
0x64 => 'moutn', 0x65 => 'xminn', 0x66 => 'extenbc', 0x67 => 'extndisc',
|
87
|
+
0x68 => 'extmin', 0x69 => 'extmout', 0x6a => 'extmin64', 0x6b => 'extmout64',
|
88
|
+
0x6c => 'postnormsn', 0x6d => 'roundsn', 0x6e => 'extminn', 0x6f => 'extmoutn',
|
89
|
+
0x70 => 'enbc3', 0x71 => 'ldinf', 0x72 => 'fmul', 0x73 => 'cflerr',
|
90
|
+
0x74 => 'crcword', 0x75 => 'crcbyte', 0x76 => 'bitcnt', 0x77 => 'bitrevword',
|
91
|
+
0x78 => 'bitrevnbits', 0x79 => 'pop', 0x7a => 'timerdisableh', 0x7b => 'timerdisablel',
|
92
|
+
0x7c => 'timerenableh', 0x7d => 'timerenablel', 0x7e => 'ldmemstartval',
|
93
|
+
0x80 => 'fpsttest', 0x81 => 'wsubdb', 0x82 => 'fpldnldbi', 0x83 => 'fpchkerr',
|
94
|
+
0x84 => 'fpstnldb', 0x85 => 'fpldtest', 0x86 => 'fpldnlsni', 0x87 => 'fpadd',
|
95
|
+
0x88 => 'fpstnlsn', 0x89 => 'fpsub', 0x8a => 'fpldnldb', 0x8b => 'fpmul',
|
96
|
+
0x8c => 'fpdiv', 0x8d => 'fprange', 0x8e => 'fpldnlsn', 0x8f => 'fpremfirst',
|
97
|
+
0x90 => 'fpremstep', 0x91 => 'fpnan', 0x92 => 'fpordered', 0x93 => 'fpnotfinite',
|
98
|
+
0x94 => 'fpgt', 0x95 => 'fpeq', 0x96 => 'fpi32tor32', 0x97 => 'fpge',
|
99
|
+
0x98 => 'fpi32tor64', 0x99 => 'enbt3', 0x9a => 'fpb32tor64', 0x9b => 'fplg',
|
100
|
+
0x9c => 'fptesterr', 0x9d => 'fprtoi32', 0x9e => 'fpstnli32', 0x9f => 'fpldzerosn',
|
101
|
+
0xa0 => 'fpldzerodb', 0xa1 => 'fpint', 0xa2 => 'getpri', 0xa3 => 'fpdup',
|
102
|
+
0xa4 => 'fprev', 0xa5 => 'setpri', 0xa6 => 'fpldnladddb', 0xa7 => 'fpentry3',
|
103
|
+
0xa8 => 'fpldnlmuldb', 0xa9 => 'fpentry2', 0xaa => 'fpldnladdsn', 0xab => 'fpentry',
|
104
|
+
0xac => 'fpldnlmulsn', 0xad => 'enbs3',
|
105
|
+
0xb0 => 'settimeslice', 0xb1 => 'break', 0xb2 => 'clrj0break', 0xb3 => 'setj0break',
|
106
|
+
0xb4 => 'testj0break', 0xb6 => 'ldflags', 0xb7 => 'stflags',
|
107
|
+
0xb8 => 'xbword', 0xb9 => 'lbx', 0xba => 'cb', 0xbb => 'cbu',
|
108
|
+
0xbc => 'insphdr', 0xbd => 'readbfr', 0xbe => 'ldconf', 0xbf => 'stconf',
|
109
|
+
0xc0 => 'ldcnt', 0xc1 => 'ssub', 0xc2 => 'ldth', 0xc3 => 'ldchstatus',
|
110
|
+
0xc4 => 'intdis', 0xc5 => 'intenb', 0xc6 => 'ldtrapped', 0xc7 => 'cir',
|
111
|
+
0xc8 => 'ss', 0xc9 => 'chantype', 0xca => 'ls', 0xcb => 'sttrapped',
|
112
|
+
0xcc => 'ciru', 0xcd => 'gintdis', 0xce => 'gintenb', 0xcf => 'fprem',
|
113
|
+
0xd0 => 'fprn', 0xd1 => 'fpdivby2', 0xd2 => 'fpmulby2', 0xd3 => 'fpsqrt',
|
114
|
+
0xd4 => 'fprp', 0xd5 => 'fprm', 0xd6 => 'fprz', 0xd7 => 'fpr32tor64',
|
115
|
+
0xd8 => 'fpr64tor32', 0xd9 => 'fpexpdec32', 0xda => 'fpexpinc32', 0xdb => 'fpabs',
|
116
|
+
0xdd => 'fpadddbsn', 0xde => 'fpchki32', 0xdf => 'fpchki64',
|
117
|
+
0xe0 => 'mnew', 0xe1 => 'mfree', 0xe2 => 'malloc', 0xe3 => 'mrelease',
|
118
|
+
0xe4 => 'min', 0xe5 => 'mout', 0xe6 => 'min64', 0xe7 => 'mout64',
|
119
|
+
0xe8 => 'xable', 0xe9 => 'xin', 0xea => 'xmin', 0xeb => 'xmin64',
|
120
|
+
0xec => 'xend', 0xed => 'ndisc', 0xee => 'ndist', 0xef => 'ndiss',
|
121
|
+
0xf0 => 'devlb', 0xf1 => 'devsb', 0xf2 => 'devls', 0xf3 => 'devss',
|
122
|
+
0xf4 => 'devlw', 0xf5 => 'devsw', 0xf8 => 'xsword', 0xf9 => 'lsx',
|
123
|
+
0xfa => 'cs', 0xfb => 'csu', 0xfc => 'trap', 0xfd => 'null',
|
124
|
+
0x1ff => 'start',
|
125
|
+
0x17c => 'lddevid',
|
126
|
+
0x200 => 'in8', 0x201 => 'in32', 0x202 => 'out8', 0x203 => 'out32',
|
127
|
+
0x204 => 'xstl',
|
128
|
+
0x22f => 'proc_alloc',
|
129
|
+
0x230 => 'proc_param', 0x231 => 'proc_mt_copy', 0x232 => 'proc_mt_move', 0x233 => 'proc_start',
|
130
|
+
0x234 => 'proc_end', 0x235 => 'getaff', 0x236 => 'setaff', 0x237 => 'getpas',
|
131
|
+
0x238 => 'mt_alloc', 0x239 => 'mt_release', 0x23a => 'mt_clone', 0x23b => 'mt_in',
|
132
|
+
0x23c => 'mt_out', 0x23d => 'mt_xchg', 0x23e => 'mt_lock', 0x23f => 'mt_unlock',
|
133
|
+
0x240 => 'mt_enroll', 0x241 => 'mt_resign', 0x242 => 'mt_sync', 0x243 => 'mt_xin',
|
134
|
+
0x244 => 'mt_xout', 0x245 => 'mt_xxchg', 0x246 => 'mt_dclone', 0x247 => 'mt_bind',
|
135
|
+
0x248 => 'mb', 0x249 => 'rmb', 0x24a => 'wmb', 0x24b => 'ext_mt_in',
|
136
|
+
0x24c => 'ext_mt_out', 0x24d => 'mt_resize',
|
137
|
+
}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -5,8 +5,7 @@
|
|
5
5
|
|
6
6
|
|
7
7
|
require 'metasm/main'
|
8
|
-
require 'metasm/
|
9
|
-
require 'metasm/
|
10
|
-
require 'metasm/
|
11
|
-
require 'metasm/
|
12
|
-
require 'metasm/arm/debug'
|
8
|
+
require 'metasm/cpu/webasm/decode'
|
9
|
+
require 'metasm/cpu/webasm/encode'
|
10
|
+
require 'metasm/cpu/webasm/decompile'
|
11
|
+
require 'metasm/cpu/webasm/debug'
|
@@ -0,0 +1,31 @@
|
|
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/webasm/opcodes'
|
8
|
+
|
9
|
+
module Metasm
|
10
|
+
class WebAsm
|
11
|
+
def dbg_register_list
|
12
|
+
@dbg_register_list ||= [:pc, :opstack, :mem, :local_base]
|
13
|
+
end
|
14
|
+
|
15
|
+
def dbg_resolve_pc(di, fbd, pc_reg, dbg_ctx)
|
16
|
+
case di.opcode.name
|
17
|
+
when 'br_if', 'if'
|
18
|
+
if dbg_ctx.resolve(Indirection[:opstack, 8]) != 0
|
19
|
+
fbd[pc_reg] = (di.opcode.name == 'if' ? di.next_addr : di.misc[:x])
|
20
|
+
else
|
21
|
+
fbd[pc_reg] = (di.opcode.name == 'if' ? di.misc[:x] : di.next_addr)
|
22
|
+
end
|
23
|
+
else return super(di, fbd, pc_reg, dbg_ctx)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def dbg_end_stepout(dbg, addr, di)
|
28
|
+
di and di.opcode.props[:stopexec] and (di.opcode.name == 'return' or di.opcode.name == 'end')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,321 @@
|
|
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/webasm/opcodes'
|
7
|
+
require 'metasm/decode'
|
8
|
+
|
9
|
+
module Metasm
|
10
|
+
class WebAsm
|
11
|
+
def build_bin_lookaside
|
12
|
+
lookaside = (0..0xff).inject({}) { |h, i| h.update i => [] }
|
13
|
+
opcode_list.each { |op|
|
14
|
+
lookaside[op.bin] << op
|
15
|
+
}
|
16
|
+
lookaside
|
17
|
+
end
|
18
|
+
|
19
|
+
def decode_uleb(ed, signed=false)
|
20
|
+
v = s = 0
|
21
|
+
while s < 10*7
|
22
|
+
b = ed.read(1).unpack('C').first.to_i
|
23
|
+
v |= (b & 0x7f) << s
|
24
|
+
s += 7
|
25
|
+
break if (b&0x80) == 0
|
26
|
+
end
|
27
|
+
v = Expression.make_signed(v, s) if signed
|
28
|
+
v
|
29
|
+
end
|
30
|
+
|
31
|
+
# when starting disassembly, pre-decode all instructions until the final 'end' and fixup the xrefs (if/block/loop...)
|
32
|
+
def disassemble_init_context(dasm, addr)
|
33
|
+
dasm.misc ||= {}
|
34
|
+
dasm.misc[:cpu_context] ||= {}
|
35
|
+
cache = dasm.misc[:cpu_context][:di_cache] ||= {}
|
36
|
+
addr = dasm.normalize(addr)
|
37
|
+
return dasm.misc[:cpu_context] if cache[addr]
|
38
|
+
|
39
|
+
code_start = addr
|
40
|
+
stack = [[]]
|
41
|
+
set_misc_x = lambda { |di, tg| di.misc[:x] ||= [] ; di.misc[:x] |= [tg] }
|
42
|
+
while di = dasm.disassemble_instruction(addr)
|
43
|
+
cache[addr] = di
|
44
|
+
di.misc ||= {}
|
45
|
+
di.misc[:code_start] = code_start
|
46
|
+
case di.opcode.name
|
47
|
+
when 'if', 'loop', 'block'
|
48
|
+
stack << [di]
|
49
|
+
when 'else'
|
50
|
+
raise "bad #{di} #{stack.last.inspect}" if stack.last.empty? or stack.last.last.opcode.name != 'if'
|
51
|
+
stack.last.each { |ddi| set_misc_x[ddi, di.next_addr] } # 'if' points past here
|
52
|
+
di.misc[:end_of] = stack.last[0] # store matching 'if'
|
53
|
+
stack.last[0] = di # 'else' replace 'if'
|
54
|
+
when 'br', 'br_if', 'br_table'
|
55
|
+
if di.opcode.name == 'br_table'
|
56
|
+
depths = di.instruction.args.first.ary.uniq | [di.instruction.args.first.default]
|
57
|
+
else
|
58
|
+
depths = [di.instruction.args.first.reduce]
|
59
|
+
end
|
60
|
+
depths.each { |depth|
|
61
|
+
tg = stack[-depth-1] # XXX skip if/else in the stack ?
|
62
|
+
raise "bad #{di} (#{stack.length})" if not tg
|
63
|
+
if tg.first and tg.first.opcode.name == 'loop'
|
64
|
+
set_misc_x[di, tg.first.address]
|
65
|
+
else
|
66
|
+
tg << di
|
67
|
+
end
|
68
|
+
}
|
69
|
+
when 'end'
|
70
|
+
dis = stack.pop
|
71
|
+
dis.each { |ddi| set_misc_x[ddi, di.next_addr] if ddi.opcode.name != 'loop' and ddi.opcode.name != 'block' }
|
72
|
+
if stack.empty?
|
73
|
+
# stack empty: end of func
|
74
|
+
di.opcode = @opcode_list.find { |op| op.name == 'end' and op.props[:stopexec] }
|
75
|
+
break
|
76
|
+
else
|
77
|
+
if dis.first
|
78
|
+
di.misc[:end_of] = dis.first # store matching loop/block/if
|
79
|
+
if dis.first.opcode.name == 'else'
|
80
|
+
di.misc[:end_of] = dis.first.misc[:end_of] # else patched stack.last, recover original 'if'
|
81
|
+
end
|
82
|
+
end
|
83
|
+
di.opcode = @opcode_list.find { |op| op.name == 'end' and not op.props[:stopexec] }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
addr = di.next_addr
|
87
|
+
end
|
88
|
+
|
89
|
+
dasm.misc[:cpu_context]
|
90
|
+
end
|
91
|
+
|
92
|
+
# reuse the instructions from the cache
|
93
|
+
def decode_instruction_context(dasm, edata, di_addr, ctx)
|
94
|
+
ctx ||= disassemble_init_context(dasm, di_addr)
|
95
|
+
if not ctx[:di_cache][di_addr]
|
96
|
+
di_addr = dasm.normalize(di_addr)
|
97
|
+
disassemble_init_context(dasm, di_addr)
|
98
|
+
end
|
99
|
+
ctx[:di_cache][di_addr]
|
100
|
+
end
|
101
|
+
|
102
|
+
def decode_findopcode(edata)
|
103
|
+
di = DecodedInstruction.new(self)
|
104
|
+
val = edata.decode_imm(:u8, @endianness)
|
105
|
+
di if di.opcode = bin_lookaside[val].first
|
106
|
+
end
|
107
|
+
|
108
|
+
def decode_instr_op(edata, di)
|
109
|
+
before_ptr = edata.ptr
|
110
|
+
op = di.opcode
|
111
|
+
di.instruction.opname = op.name
|
112
|
+
|
113
|
+
op.args.each { |a|
|
114
|
+
di.instruction.args << case a
|
115
|
+
when :f32; Expression[edata.decode_imm(:u32, @endianness)]
|
116
|
+
when :f64; Expression[edata.decode_imm(:u64, @endianness)]
|
117
|
+
when :memoff; Memref.new(decode_uleb(edata))
|
118
|
+
when :uleb; Expression[decode_uleb(edata)]
|
119
|
+
when :sleb; Expression[decode_uleb(edata, true)]
|
120
|
+
when :blocksig; BlockSignature.new(decode_uleb(edata, true))
|
121
|
+
when :br_table; decode_br_table(edata)
|
122
|
+
else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
|
123
|
+
end
|
124
|
+
}
|
125
|
+
|
126
|
+
di.bin_length = 1 + edata.ptr - before_ptr
|
127
|
+
di
|
128
|
+
end
|
129
|
+
|
130
|
+
def decode_instr_interpret(di, addr)
|
131
|
+
case di.opcode.name
|
132
|
+
when 'call'
|
133
|
+
fnr = di.instruction.args.first.reduce
|
134
|
+
di.misc ||= {}
|
135
|
+
di.misc[:tg_func_nr] = fnr
|
136
|
+
if f = @wasm_file.get_function_nr(fnr)
|
137
|
+
tg = f[:init_offset] ? f[:init_offset] : "#{f[:module]}_#{f[:field]}"
|
138
|
+
di.instruction.args[0] = Expression[tg]
|
139
|
+
di.misc[:x] = [tg]
|
140
|
+
else
|
141
|
+
di.misc[:x] = [:default]
|
142
|
+
end
|
143
|
+
when 'call_indirect'
|
144
|
+
di.misc ||= {}
|
145
|
+
di.misc[:x] = [:default]
|
146
|
+
end
|
147
|
+
di
|
148
|
+
end
|
149
|
+
|
150
|
+
def decode_br_table(edata)
|
151
|
+
count = decode_uleb(edata)
|
152
|
+
ary = []
|
153
|
+
count.times { ary << decode_uleb(edata) }
|
154
|
+
default = decode_uleb(edata)
|
155
|
+
BrTable.new(ary, default)
|
156
|
+
end
|
157
|
+
|
158
|
+
def init_backtrace_binding
|
159
|
+
@backtrace_binding ||= {}
|
160
|
+
|
161
|
+
typesz = Hash.new(8).update 'i32' => 4, 'f32' => 4
|
162
|
+
opstack = lambda { |off, sz| Indirection[Expression[:opstack, :+, off].reduce, sz] }
|
163
|
+
add_opstack = lambda { |delta, hash| { :opstack => Expression[:opstack, :+, delta].reduce }.update hash }
|
164
|
+
globsz = lambda { |di|
|
165
|
+
glob_nr = Expression[di.instruction.args.first].reduce
|
166
|
+
g = @wasm_file.get_global_nr(glob_nr)
|
167
|
+
g ? typesz[g[:type]] : 8
|
168
|
+
}
|
169
|
+
global = lambda { |di|
|
170
|
+
glob_nr = Expression[di.instruction.args.first].reduce
|
171
|
+
g = @wasm_file.get_global_nr(glob_nr)
|
172
|
+
n = g && g[:module] ? "#{g[:module]}_#{g[:field]}" : "global_#{glob_nr}"
|
173
|
+
Indirection[n, globsz[di]]
|
174
|
+
}
|
175
|
+
locsz = lambda { |di|
|
176
|
+
loc_nr = Expression[di.instruction.args.first].reduce
|
177
|
+
ci = @wasm_file.code_info[di.misc[:code_start]]
|
178
|
+
next typesz[ci[:params][loc_nr]] if loc_nr < ci[:params].length
|
179
|
+
loc_nr -= ci[:params].length
|
180
|
+
next typesz[ci[:local_var][loc_nr]] if ci[:local_var][loc_nr]
|
181
|
+
8
|
182
|
+
}
|
183
|
+
local = lambda { |di|
|
184
|
+
loc_nr = Expression[di.instruction.args.first].reduce
|
185
|
+
Indirection[[:local_base, :+, loc_nr*8], locsz[di]]
|
186
|
+
}
|
187
|
+
|
188
|
+
opcode_list.map { |ol| ol.name }.uniq.each { |opname|
|
189
|
+
sz = (opname[1, 2] == '32' ? 4 : 8)
|
190
|
+
@backtrace_binding[opname] ||= case opname
|
191
|
+
when 'call', 'call_indirect'
|
192
|
+
lambda { |di|
|
193
|
+
stack_off = 0
|
194
|
+
if opname == 'call'
|
195
|
+
f = @wasm_file.get_function_nr(di.misc[:tg_func_nr])
|
196
|
+
proto = f ? f[:type] : {}
|
197
|
+
# TODO use local_base
|
198
|
+
h = { :callstack => Expression[:callstack, :+, 8], Indirection[:callstack, 8] => Expression[di.next_addr] }
|
199
|
+
proto_params_offset = 0
|
200
|
+
else
|
201
|
+
proto = @wasm_file.type[di.instruction.args.first.reduce]
|
202
|
+
h = { :callstack => Expression[:callstack, :+, 8], Indirection[:callstack, 8] => Expression[di.next_addr], 'func_idx' => Expression[opstack[0, 4]] }
|
203
|
+
stack_off += 8
|
204
|
+
proto_params_offset = 1
|
205
|
+
end
|
206
|
+
stack_off -= 8*proto[:ret].to_a.length
|
207
|
+
stack_off += 8*proto[:params].to_a.length
|
208
|
+
h.update :opstack => Expression[:opstack, :+, stack_off]
|
209
|
+
proto[:ret].to_a.each_with_index { |rt, i| h.update opstack[8*i, typesz[rt]] => Expression["ret_#{i}"] }
|
210
|
+
proto[:params].to_a.each_with_index { |pt, i| h.update "param_#{i}" => Expression[opstack[8*(proto[:params].length-i-1+proto_params_offset), typesz[pt]]] }
|
211
|
+
h
|
212
|
+
}
|
213
|
+
when 'if', 'br_if'; lambda { |di| add_opstack[ 8, :flag => Expression[opstack[0, 8]]] }
|
214
|
+
when 'block', 'loop', 'br', 'nop', 'else'; lambda { |di| {} }
|
215
|
+
when 'end', 'return'; lambda { |di| di.opcode.props[:stopexec] ? { :callstack => Expression[:callstack, :-, 8] } : {} }
|
216
|
+
when 'drop'; lambda { |di| add_opstack[8, {}] }
|
217
|
+
when 'select'; lambda { |di| add_opstack[16, opstack[0, 8] => Expression[[opstack[8, 8], :*, [1, :-, opstack[0, 8]]], :|, [opstack[16, 8], :*, opstack[0, 8]]]] }
|
218
|
+
when 'get_local'; lambda { |di| add_opstack[-8, opstack[0, locsz[di]] => Expression[local[di]]] }
|
219
|
+
when 'set_local'; lambda { |di| add_opstack[ 8, local[di] => Expression[opstack[0, locsz[di]]]] }
|
220
|
+
when 'tee_local'; lambda { |di| add_opstack[ 0, local[di] => Expression[opstack[0, locsz[di]]]] }
|
221
|
+
when 'get_global'; lambda { |di| add_opstack[-8, opstack[0, globsz[di]] => Expression[global[di]]] }
|
222
|
+
when 'set_global'; lambda { |di| add_opstack[ 8, global[di] => Expression[opstack[0, globsz[di]]]] }
|
223
|
+
when /\.load(.*)/
|
224
|
+
mode = $1; memsz = (mode.include?('32') ? 4 : mode.include?('16') ? 2 : mode.include?('8') ? 1 : sz)
|
225
|
+
lambda { |di| add_opstack[ 0, opstack[0, sz] => Expression[Indirection[[opstack[0, 4], :+, [:mem, :+, di.instruction.args[1].off]], memsz]]] }
|
226
|
+
when /\.store(.*)/
|
227
|
+
mode = $1; memsz = (mode.include?('32') ? 4 : mode.include?('16') ? 2 : mode.include?('8') ? 1 : sz)
|
228
|
+
lambda { |di| add_opstack[ 16, Indirection[[opstack[8, 4], :+, [:mem, :+, di.instruction.args[1].off]], memsz] => Expression[opstack[0, sz], :&, (1 << (8*memsz)) - 1]] }
|
229
|
+
when /\.const/; lambda { |di| add_opstack[-8, opstack[0, sz] => Expression[di.instruction.args.first.reduce]] }
|
230
|
+
when /\.eqz/; lambda { |di| add_opstack[ 0, opstack[0, 8] => Expression[opstack[0, sz], :==, 0]] }
|
231
|
+
when /\.eq/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :==, opstack[0, sz]]] }
|
232
|
+
when /\.ne/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :!=, opstack[0, sz]]] }
|
233
|
+
when /\.lt/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :<, opstack[0, sz]]] }
|
234
|
+
when /\.gt/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :>, opstack[0, sz]]] }
|
235
|
+
when /\.le/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :<=, opstack[0, sz]]] }
|
236
|
+
when /\.ge/; lambda { |di| add_opstack[ 8, opstack[0, 8] => Expression[opstack[8, sz], :>=, opstack[0, sz]]] }
|
237
|
+
|
238
|
+
when /\.(clz|ctz|popcnt)/; lambda { |di| add_opstack[ 0, :bits => Expression[opstack[0, sz]]] }
|
239
|
+
when /\.add/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :+, opstack[0, sz]]] }
|
240
|
+
when /\.sub/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :-, opstack[0, sz]]] }
|
241
|
+
when /\.mul/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :*, opstack[0, sz]]] }
|
242
|
+
when /\.div/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :/, opstack[0, sz]]] }
|
243
|
+
when /\.rem/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :%, opstack[0, sz]]] }
|
244
|
+
when /\.and/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :&, opstack[0, sz]]] }
|
245
|
+
when /\.or/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :|, opstack[0, sz]]] }
|
246
|
+
when /\.xor/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :^, opstack[0, sz]]] }
|
247
|
+
when /\.shl/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :<<, opstack[0, sz]]] }
|
248
|
+
when /\.shr/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[opstack[8, sz], :>>, opstack[0, sz]]] }
|
249
|
+
when /\.rotl/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[[opstack[8, sz], :<<, opstack[0, sz]], :|, [opstack[8, sz], :>>, [8*sz, :-, opstack[0, sz]]]]] }
|
250
|
+
when /\.rotr/; lambda { |di| add_opstack[ 8, opstack[0, sz] => Expression[[opstack[8, sz], :>>, opstack[0, sz]], :|, [opstack[8, sz], :<<, [8*sz, :-, opstack[0, sz]]]]] }
|
251
|
+
when /f.*\.(abs|neg|ceil|floor|trunc|nearest|sqrt|copysign)/; lambda { |di| add_opstack[0, :incomplete_binding => 1] }
|
252
|
+
when /f.*\.(min|max)/; lambda { |di| add_opstack[8, :incomplete_binding => 1] }
|
253
|
+
when /i32.wrap/; lambda { |di| add_opstack[ 0, opstack[0, 4] => Expression[opstack[0, 8]]] }
|
254
|
+
when /i64.extend/; lambda { |di| add_opstack[ 0, opstack[0, 8] => Expression[opstack[0, 4]]] }
|
255
|
+
when /trunc|convert|promote|demote|reinterpret/; lambda { |di| add_opstack[0, :incomplete_binding => 1] }
|
256
|
+
end
|
257
|
+
}
|
258
|
+
|
259
|
+
@backtrace_binding
|
260
|
+
end
|
261
|
+
|
262
|
+
def get_backtrace_binding(di)
|
263
|
+
if binding = backtrace_binding[di.opcode.name]
|
264
|
+
binding[di] || {}
|
265
|
+
else
|
266
|
+
puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
|
267
|
+
{:incomplete_binding => Expression[1]}
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
def fix_fwdemu_binding(di, fbd)
|
272
|
+
ori = fbd
|
273
|
+
fbd = {}
|
274
|
+
ori.each { |k, v|
|
275
|
+
if k.kind_of?(Indirection) and not k.target.lexpr.kind_of?(Indirection)
|
276
|
+
# dont fixup store8 etc
|
277
|
+
fbd[k.bind(:opstack => ori[:opstack]).reduce_rec] = v
|
278
|
+
else
|
279
|
+
fbd[k] = v
|
280
|
+
end
|
281
|
+
}
|
282
|
+
fbd
|
283
|
+
end
|
284
|
+
|
285
|
+
def get_xrefs_x(dasm, di)
|
286
|
+
if di.opcode.props[:stopexec]
|
287
|
+
case di.opcode.name
|
288
|
+
when 'return', 'end'
|
289
|
+
return [Indirection[:callstack, 8]]
|
290
|
+
end
|
291
|
+
end
|
292
|
+
return [] if not di.opcode.props[:setip]
|
293
|
+
|
294
|
+
di.misc ? [di.misc[:x]].flatten : []
|
295
|
+
end
|
296
|
+
|
297
|
+
def backtrace_is_function_return(expr, di=nil)
|
298
|
+
expr and Expression[expr] == Expression[Indirection[:callstack, 8]]
|
299
|
+
end
|
300
|
+
|
301
|
+
def disassembler_default_func
|
302
|
+
df = DecodedFunction.new
|
303
|
+
ra = Indirection[:callstack, 8]
|
304
|
+
df.backtracked_for << BacktraceTrace.new(ra, :default, ra, :x, nil)
|
305
|
+
df.backtrace_binding = { :callstack => Expression[:callstack, :-, 8] }
|
306
|
+
df
|
307
|
+
end
|
308
|
+
|
309
|
+
def backtrace_update_function_binding(dasm, faddr, f, retaddrlist, *wantregs)
|
310
|
+
f.backtrace_binding = { :callstack => Expression[:callstack, :-, 8] }
|
311
|
+
end
|
312
|
+
|
313
|
+
def backtrace_is_stack_address(expr)
|
314
|
+
([:local_base, :opstack] & Expression[expr].expr_externals).first
|
315
|
+
end
|
316
|
+
|
317
|
+
def decode_c_function_prototype(cp, sym, orig=nil)
|
318
|
+
disassembler_default_func
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|