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
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
require 'metasm/arm/opcodes'
|
|
7
|
+
require 'metasm/cpu/arm/opcodes'
|
|
8
8
|
require 'metasm/parse'
|
|
9
9
|
|
|
10
10
|
module Metasm
|
|
@@ -26,24 +26,32 @@ class ARM
|
|
|
26
26
|
|
|
27
27
|
def parse_arg_valid?(op, sym, arg)
|
|
28
28
|
case sym
|
|
29
|
-
when :rd, :rs, :rn, :rm; arg.kind_of?
|
|
30
|
-
when :rm_rs; arg.kind_of?
|
|
31
|
-
when :rm_is; arg.kind_of?
|
|
32
|
-
when :
|
|
29
|
+
when :rd, :rs, :rn, :rm; arg.kind_of?(Reg) and arg.shift == 0 and (arg.updated ? op.props[:baseincr] : !op.props[:baseincr])
|
|
30
|
+
when :rm_rs; arg.kind_of?(Reg) and arg.shift.kind_of?(Reg)
|
|
31
|
+
when :rm_is; arg.kind_of?(Reg) and arg.shift.kind_of?(Integer)
|
|
32
|
+
when :i12, :i24, :i8_12; arg.kind_of?(Expression)
|
|
33
|
+
when :i8_r
|
|
34
|
+
if arg.kind_of?(Expression)
|
|
35
|
+
b = arg.reduce
|
|
36
|
+
!b.kind_of?(Integer) or (0..15).find {
|
|
37
|
+
b = ((b << 2) & 0xffff_ffff) | ((b >> 30) & 3)
|
|
38
|
+
b < 0x100 }
|
|
39
|
+
end
|
|
33
40
|
when :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12
|
|
34
41
|
os = case sym
|
|
35
42
|
when :mem_rn_rm; :rm
|
|
36
43
|
when :mem_rn_i8_12; :i8_12
|
|
37
44
|
when :mem_rn_rms; :rm_rs
|
|
38
|
-
when :mem_rn_i12; :
|
|
45
|
+
when :mem_rn_i12; :i12
|
|
39
46
|
end
|
|
40
|
-
arg.kind_of?
|
|
41
|
-
when :reglist; arg.kind_of?
|
|
47
|
+
arg.kind_of?(Memref) and parse_arg_valid?(op, os, arg.offset)
|
|
48
|
+
when :reglist; arg.kind_of?(RegList)
|
|
42
49
|
end
|
|
43
50
|
# TODO check flags on reglist, check int values
|
|
44
51
|
end
|
|
45
52
|
|
|
46
53
|
def parse_argument(lexer)
|
|
54
|
+
raise lexer, "unexpected EOS" if not lexer.nexttok
|
|
47
55
|
if Reg.s_to_i[lexer.nexttok.raw]
|
|
48
56
|
arg = Reg.new Reg.s_to_i[lexer.readtok.raw]
|
|
49
57
|
lexer.skip_space
|
|
@@ -62,22 +70,24 @@ class ARM
|
|
|
62
70
|
when '!'
|
|
63
71
|
lexer.readtok
|
|
64
72
|
arg.updated = true
|
|
65
|
-
end
|
|
73
|
+
end if lexer.nexttok
|
|
66
74
|
elsif lexer.nexttok.raw == '{'
|
|
67
75
|
lexer.readtok
|
|
68
76
|
arg = RegList.new
|
|
69
77
|
loop do
|
|
70
|
-
raise "unterminated reglist" if lexer.eos?
|
|
71
78
|
lexer.skip_space
|
|
79
|
+
raise "unterminated reglist" if lexer.eos?
|
|
72
80
|
if Reg.s_to_i[lexer.nexttok.raw]
|
|
73
81
|
arg.list << Reg.new(Reg.s_to_i[lexer.readtok.raw])
|
|
74
82
|
lexer.skip_space
|
|
83
|
+
raise "unterminated reglist" if lexer.eos?
|
|
75
84
|
end
|
|
76
85
|
case lexer.nexttok.raw
|
|
77
86
|
when ','; lexer.readtok
|
|
78
87
|
when '-'
|
|
79
88
|
lexer.readtok
|
|
80
89
|
lexer.skip_space
|
|
90
|
+
raise "unterminated reglist" if lexer.eos?
|
|
81
91
|
if not r = Reg.s_to_i[lexer.nexttok.raw]
|
|
82
92
|
raise lexer, "reglist parse error: invalid range"
|
|
83
93
|
end
|
|
@@ -95,20 +105,22 @@ class ARM
|
|
|
95
105
|
end
|
|
96
106
|
elsif lexer.nexttok.raw == '['
|
|
97
107
|
lexer.readtok
|
|
108
|
+
raise "unexpected EOS" if lexer.eos?
|
|
98
109
|
if not base = Reg.s_to_i[lexer.nexttok.raw]
|
|
99
110
|
raise lexer, 'invalid mem base (reg expected)'
|
|
100
111
|
end
|
|
101
112
|
base = Reg.new Reg.s_to_i[lexer.readtok.raw]
|
|
113
|
+
raise "unexpected EOS" if lexer.eos?
|
|
102
114
|
if lexer.nexttok.raw == ']'
|
|
103
115
|
lexer.readtok
|
|
104
|
-
closed = true
|
|
116
|
+
#closed = true
|
|
105
117
|
end
|
|
106
|
-
if lexer.nexttok.raw != ','
|
|
118
|
+
if !lexer.nexttok or lexer.nexttok.raw != ','
|
|
107
119
|
raise lexer, 'mem off expected'
|
|
108
120
|
end
|
|
109
121
|
lexer.readtok
|
|
110
122
|
off = parse_argument(lexer)
|
|
111
|
-
if not off.kind_of?
|
|
123
|
+
if not off.kind_of?(Expression) and not off.kind_of?(Reg)
|
|
112
124
|
raise lexer, 'invalid mem off (reg/imm expected)'
|
|
113
125
|
end
|
|
114
126
|
case lexer.nexttok and lexer.nexttok.raw
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
5
|
|
|
6
6
|
require 'metasm/render'
|
|
7
|
-
require 'metasm/arm/opcodes'
|
|
7
|
+
require 'metasm/cpu/arm/opcodes'
|
|
8
8
|
|
|
9
9
|
module Metasm
|
|
10
10
|
class ARM
|
|
@@ -19,7 +19,7 @@ class ARM
|
|
|
19
19
|
["#{r} RRX"]
|
|
20
20
|
else
|
|
21
21
|
case s = @shift
|
|
22
|
-
when Integer; s = Expression[s]
|
|
22
|
+
when Integer; s = Expression[s == 0 ? 32 : s] # lsl and ror already accounted for
|
|
23
23
|
when Reg; s = self.class.i_to_s[s.i]
|
|
24
24
|
end
|
|
25
25
|
["#{r} #{@stype.to_s.upcase} #{s}"]
|
data/metasm/cpu/arm64.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
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
|
+
class Metasm::ARM64 < Metasm::CPU
|
|
7
|
+
end
|
|
8
|
+
Metasm::AArch64 = Metasm::ARM64
|
|
9
|
+
|
|
10
|
+
require 'metasm/main'
|
|
11
|
+
require 'metasm/cpu/arm64/parse'
|
|
12
|
+
require 'metasm/cpu/arm64/encode'
|
|
13
|
+
require 'metasm/cpu/arm64/decode'
|
|
14
|
+
require 'metasm/cpu/arm64/render'
|
|
15
|
+
require 'metasm/cpu/arm64/debug'
|
|
@@ -0,0 +1,38 @@
|
|
|
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/arm64/opcodes'
|
|
8
|
+
|
|
9
|
+
module Metasm
|
|
10
|
+
class ARM64
|
|
11
|
+
def dbg_register_pc
|
|
12
|
+
@dbg_register_pc ||= :pc
|
|
13
|
+
end
|
|
14
|
+
def dbg_register_flags
|
|
15
|
+
@dbg_register_flags ||= :flags
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def dbg_register_list
|
|
19
|
+
@dbg_register_list ||= Reg::Sym.sort.transpose[1] - [:xzr]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def dbg_flag_list
|
|
23
|
+
@dbg_flag_list ||= []
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def dbg_register_size
|
|
27
|
+
@dbg_register_size ||= Hash.new(64)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def dbg_need_stepover(dbg, addr, di)
|
|
31
|
+
di and di.opcode.props[:saveip]
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def dbg_end_stepout(dbg, addr, di)
|
|
35
|
+
di and di.opcode.name == 'foobar'
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,289 @@
|
|
|
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/arm64/opcodes'
|
|
7
|
+
require 'metasm/decode'
|
|
8
|
+
|
|
9
|
+
module Metasm
|
|
10
|
+
class ARM64
|
|
11
|
+
# create the bin_mask for a given opcode
|
|
12
|
+
def build_opcode_bin_mask(op)
|
|
13
|
+
# bit = 0 if can be mutated by an field value, 1 if fixed by opcode
|
|
14
|
+
op.bin_mask = 0
|
|
15
|
+
op.fields.each { |k, (m, s)|
|
|
16
|
+
op.bin_mask |= m << s
|
|
17
|
+
}
|
|
18
|
+
op.bin_mask = 0xffffffff ^ op.bin_mask
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# create the lookaside hash from the first byte of the opcode
|
|
22
|
+
def build_bin_lookaside
|
|
23
|
+
lookaside = Array.new(256) { [] }
|
|
24
|
+
|
|
25
|
+
opcode_list.each { |op|
|
|
26
|
+
build_opcode_bin_mask op
|
|
27
|
+
|
|
28
|
+
b = (op.bin >> 24) & 0xff
|
|
29
|
+
msk = (op.bin_mask >> 24) & 0xff
|
|
30
|
+
b &= msk
|
|
31
|
+
|
|
32
|
+
for i in b..(b | (255^msk))
|
|
33
|
+
lookaside[i] << op if i & msk == b
|
|
34
|
+
end
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
lookaside
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def decode_findopcode(edata)
|
|
41
|
+
return if edata.ptr+4 > edata.length
|
|
42
|
+
di = DecodedInstruction.new(self)
|
|
43
|
+
val = edata.decode_imm(:u32, @endianness)
|
|
44
|
+
di.raw_data = val
|
|
45
|
+
di if di.opcode = @bin_lookaside[(val >> 24) & 0xff].find { |op|
|
|
46
|
+
(op.bin & op.bin_mask) == (val & op.bin_mask)
|
|
47
|
+
}
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def disassembler_default_func
|
|
51
|
+
df = DecodedFunction.new
|
|
52
|
+
df
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def decode_instr_op(edata, di)
|
|
56
|
+
op = di.opcode
|
|
57
|
+
di.instruction.opname = op.name
|
|
58
|
+
val = di.raw_data
|
|
59
|
+
|
|
60
|
+
field_val = lambda { |f|
|
|
61
|
+
(val >> @fields_shift[f]) & @fields_mask[f]
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
op.args.each { |a|
|
|
65
|
+
di.instruction.args << case a
|
|
66
|
+
when :rn, :rt, :rt2, :rm
|
|
67
|
+
nr = field_val[a]
|
|
68
|
+
nr = 32 if nr == 31 and op.props[:r_z]
|
|
69
|
+
Reg.new nr, (op.props[:r_32] ? 32 : 64)
|
|
70
|
+
when :rm_lsl_i6, :rm_lsr_i6, :rm_asr_i6, :rm_lsl_i5, :rm_lsr_i5, :rm_asr_i5
|
|
71
|
+
nr = field_val[:rm]
|
|
72
|
+
nr = 32 if nr == 31 and op.props[:r_z]
|
|
73
|
+
r = Reg.new nr, (op.props[:r_32] ? 32 : 64)
|
|
74
|
+
shift = field_val[:i6_10]
|
|
75
|
+
mode = { :rm_lsl_i6 => :lsl, :rm_lsl_i5 => :lsl,
|
|
76
|
+
:rm_lsr_i6 => :lsr, :rm_lsr_i5 => :lsr,
|
|
77
|
+
:rm_asr_i6 => :asr, :rm_asr_i5 => :asr }[a]
|
|
78
|
+
RegShift.new r, mode, shift
|
|
79
|
+
when :m_rm_extend, :rm_extend_i3
|
|
80
|
+
nr = field_val[:rm]
|
|
81
|
+
nr = 32 if nr == 31
|
|
82
|
+
x = field_val[:regextend_13]
|
|
83
|
+
case a
|
|
84
|
+
when :m_rm_extend
|
|
85
|
+
shift = 0 # field_val[:i1_12] -- bug in arm doc ?
|
|
86
|
+
mode = [ :resv000, :resv001, :uxtw, :lsl, :resv100, :resv101, :sxtw, :sxtx ][x]
|
|
87
|
+
rm = RegShift.new Reg.new(nr, 64), mode, shift
|
|
88
|
+
|
|
89
|
+
rn = Reg.new field_val[:rn], 64
|
|
90
|
+
|
|
91
|
+
mem_sz = op.props[:mem_sz] || (op.props[:r_32] ? 4 : 8)
|
|
92
|
+
Memref.new(rn, rm, 1, nil, mem_sz)
|
|
93
|
+
when :rm_extend_i3
|
|
94
|
+
r = Reg.new nr, (op.props[:r_32] ? 32 : 64)
|
|
95
|
+
shift = field_val[:i3_10]
|
|
96
|
+
mode = [ :uxtb, :uxth, :uxtw, :uxtx, :sxtb, :sxth, :sxtw, :sxtx ][x]
|
|
97
|
+
RegShift.new r, mode, shift
|
|
98
|
+
end
|
|
99
|
+
when :i16_5; Expression[field_val[a]]
|
|
100
|
+
when :il18_5;
|
|
101
|
+
v = field_val[a]
|
|
102
|
+
s = (v >> 16) & 3
|
|
103
|
+
v = v & 0xffff
|
|
104
|
+
Expression[v, :<<, (16*s)]
|
|
105
|
+
when :i19_5; Expression[Expression.make_signed(field_val[a], 19) << 2]
|
|
106
|
+
when :i26_0; Expression[Expression.make_signed(field_val[a], 26) << 2]
|
|
107
|
+
when :i12_10_s1
|
|
108
|
+
f = field_val[a]
|
|
109
|
+
f = (f & 0xfff) << 12 if (f >> 12) & 1 == 1
|
|
110
|
+
Expression[f]
|
|
111
|
+
when :i19_5_2_29
|
|
112
|
+
Expression.make_signed((field_val[:i19_5] << 2) | field_val[:i2_29], 21)
|
|
113
|
+
when :bitmask, :bitmask_imm
|
|
114
|
+
n = field_val[:bitmask_n]
|
|
115
|
+
s = field_val[:bitmask_s]
|
|
116
|
+
r = field_val[:bitmask_r]
|
|
117
|
+
# highestsetbit stuff
|
|
118
|
+
levels = ((n << 6) | (s ^ 0x3f)) >> 1
|
|
119
|
+
levels = levels | (levels >> 1)
|
|
120
|
+
levels = levels | (levels >> 2)
|
|
121
|
+
levels = levels | (levels >> 4)
|
|
122
|
+
esize = levels + 1
|
|
123
|
+
s &= levels
|
|
124
|
+
r &= levels
|
|
125
|
+
welem = (1 << (s+1)) - 1
|
|
126
|
+
# ROR(welem, r)
|
|
127
|
+
wmask = ((welem >> (r % esize)) | (welem << (esize - (r % esize))))
|
|
128
|
+
wmask &= (1 << esize) - 1
|
|
129
|
+
# duplicate(wmask, sz)
|
|
130
|
+
while esize < 64
|
|
131
|
+
wmask |= wmask << esize
|
|
132
|
+
esize *= 2
|
|
133
|
+
end
|
|
134
|
+
wmask &= (1 << di.instruction.args[0].sz) - 1
|
|
135
|
+
Expression[wmask]
|
|
136
|
+
|
|
137
|
+
when :m_rn_s9, :m_rn_u12, :m_rn_s7
|
|
138
|
+
r = Reg.new(field_val[:rn], 64)
|
|
139
|
+
o = case a
|
|
140
|
+
when :m_rn_s9; Expression.make_signed(field_val[:s9_12], 9)
|
|
141
|
+
when :m_rn_s7; Expression.make_signed(field_val[:s7_15], 7)
|
|
142
|
+
when :m_rn_u12; field_val[:u12_10]
|
|
143
|
+
else raise SyntaxError, "Internal error #{a.inspect} in #{op.name}"
|
|
144
|
+
end
|
|
145
|
+
mem_sz = op.props[:mem_sz] || (op.props[:r_32] ? 4 : 8)
|
|
146
|
+
Memref.new(r, nil, nil, Expression[o*mem_sz], mem_sz, op.props[:mem_incr])
|
|
147
|
+
when :cond_12
|
|
148
|
+
RegCC.new OP_CC[field_val[a]]
|
|
149
|
+
else raise SyntaxError, "Internal error: invalid argument #{a.inspect} in #{op.name}"
|
|
150
|
+
end
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
di.bin_length = 4
|
|
154
|
+
di
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def decode_instr_interpret(di, addr)
|
|
158
|
+
if di.opcode.props[:setip] and di.instruction.args.last.kind_of?(Expression)
|
|
159
|
+
di.instruction.args[-1] = Expression[Expression[addr, :+, di.instruction.args[-1]].reduce]
|
|
160
|
+
elsif di.opcode.props[:pcrel]
|
|
161
|
+
di.instruction.args[-1] = Expression[Expression[addr, :+, di.instruction.args[-1]].reduce]
|
|
162
|
+
elsif di.opcode.props[:pcrel_page]
|
|
163
|
+
di.instruction.args[-1] = Expression[Expression[[addr, :&, ~0xfff], :+, [di.instruction.args[-1], :<<, 12]].reduce]
|
|
164
|
+
end
|
|
165
|
+
di
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def backtrace_binding
|
|
169
|
+
@backtrace_binding ||= init_backtrace_binding
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def init_backtrace_binding
|
|
173
|
+
@backtrace_binding ||= {}
|
|
174
|
+
|
|
175
|
+
opcode_list.map { |ol| ol.basename }.uniq.sort.each { |op|
|
|
176
|
+
binding = case op
|
|
177
|
+
when 'mov', 'adr', 'adrp'; lambda { |di, a0, a1| { a0 => Expression[a1] } }
|
|
178
|
+
when 'movz'; lambda { |di, a0, a1| { a0 => Expression[a1] } }
|
|
179
|
+
when 'movn'; lambda { |di, a0, a1| { a0 => Expression[:~, a1] } }
|
|
180
|
+
#when 'movk'; lambda { |di, a0, a1| a1 + lsl replace target bits of a0, other unchanged
|
|
181
|
+
when 'and', 'ands', 'orr', 'or', 'eor', 'xor'
|
|
182
|
+
bin_op = { 'and' => :&, 'ands' => :&, 'orr' => :|,
|
|
183
|
+
'or' => :|, 'eor' => :^, 'xor' => :^ }[op]
|
|
184
|
+
lambda { |di, a0, a1, a2| { a0 => Expression[ a1, bin_op, a2 ] } }
|
|
185
|
+
when 'orn', 'eorn', 'bic', 'bics', 'andn'
|
|
186
|
+
bin_op = { 'orn' => :|, 'eorn' => :^, 'andn' => :&, 'bic' => :&, 'bics' => :& }[op]
|
|
187
|
+
lambda { |di, a0, a1, a2| { a0 => Expression[ a1, bin_op, [ :~, a2 ] ] } }
|
|
188
|
+
when 'add', 'adds', 'sub', 'subs'
|
|
189
|
+
bin_op = { 'add' => :+, 'adds' => :+, 'sub' => :-, 'subs' => :- }[op]
|
|
190
|
+
lambda { |di, a0, a1, a2| { a0 => Expression[ a1, bin_op, a2 ] } }
|
|
191
|
+
when 'ldr', 'ldrb', 'ldrsw'; lambda { |di, a0, a1| { a0 => Expression[a1] } }
|
|
192
|
+
when 'str', 'strb', 'strsw'; lambda { |di, a0, a1| { a1 => Expression[a0] } }
|
|
193
|
+
when 'stp'; lambda { |di, a0, a1, a2| ptr = a2.target
|
|
194
|
+
{ Indirection[ptr, 8] => Expression[a0], Indirection[Expression[ptr, :+, 8].reduce, 8] => Expression[a1] } }
|
|
195
|
+
when 'ldp'; lambda { |di, a0, a1, a2| ptr = a2.target
|
|
196
|
+
{ a0 => Indirection[ptr, 8], a1 => Indirection[Expression[ptr, :+, 8].reduce, 8] } }
|
|
197
|
+
when 'ret'; lambda { |di, *a| { } }
|
|
198
|
+
when 'bl', 'blr'; lambda { |di, *a| { :x30 => Expression[di.next_addr] } }
|
|
199
|
+
when 'cbz', 'cbnz', 'cmp', /^b/; lambda { |di, *a| {} }
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
# pre/post-increment memref done in def get_backtrace_binding(di)
|
|
203
|
+
|
|
204
|
+
@backtrace_binding[op] ||= binding
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
@backtrace_binding
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
def get_backtrace_binding(di)
|
|
211
|
+
a = di.instruction.args.map { |arg|
|
|
212
|
+
case arg
|
|
213
|
+
when Reg, RegShift, RegCC; arg.symbolic
|
|
214
|
+
when Memref; arg.symbolic(di.address)
|
|
215
|
+
else arg
|
|
216
|
+
end
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if binding = backtrace_binding[di.opcode.name]
|
|
220
|
+
bd = binding[di, *a] || {}
|
|
221
|
+
|
|
222
|
+
# handle pre-increment / post-increment memrefs
|
|
223
|
+
di.instruction.args.grep(Memref).each { |m|
|
|
224
|
+
next unless r = m.base and r.kind_of?(Reg)
|
|
225
|
+
case m.incr
|
|
226
|
+
when :pre
|
|
227
|
+
# for di "str x1, [sp+10]!" ; bt_bind should be { sp += 10, [sp] = x1 } but memref.symbolic returns [sp+10]
|
|
228
|
+
# eg: str x30, [sp-20]! ; ldr x30, [sp], 20 ; ret should backtrace as x30 -> [sp] -!> x30
|
|
229
|
+
rs = r.symbolic
|
|
230
|
+
bd.dup.each_key { |k|
|
|
231
|
+
if k.kind_of?(Indirection)
|
|
232
|
+
bd[Indirection[k.target.bind(rs => Expression[rs, :-, m.offset]).reduce, k.len, k.origin]] = bd.delete(k)
|
|
233
|
+
end
|
|
234
|
+
}
|
|
235
|
+
bd[rs] ||= Expression[rs, :+, m.offset]
|
|
236
|
+
when :post
|
|
237
|
+
bd[r.symbolic] ||= Expression[r.symbolic, :+, m.offset]
|
|
238
|
+
end
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
# handle subregisters (x30 -> w30)
|
|
242
|
+
bd.keys.grep(Expression).each { |e|
|
|
243
|
+
# must be Expression[reg, :&, 0xffff_ffff]
|
|
244
|
+
if e.op == :& and e.rexpr == 0xffff_ffff
|
|
245
|
+
reg = e.lexpr
|
|
246
|
+
next if not reg.kind_of? Symbol
|
|
247
|
+
val = bd.delete e
|
|
248
|
+
bd[reg] = Expression[[reg, :&, 0xffff_ffff_0000_0000], :|, [val, :&, 0xffff_ffff]]
|
|
249
|
+
end
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
bd
|
|
253
|
+
else
|
|
254
|
+
puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
|
|
255
|
+
# assume nothing except the 1st arg is modified
|
|
256
|
+
case a[0]
|
|
257
|
+
when Indirection, Symbol; { a[0] => Expression::Unknown }
|
|
258
|
+
when Expression; (x = a[0].externals.first) ? { x => Expression::Unknown } : {}
|
|
259
|
+
else {}
|
|
260
|
+
end.update(:incomplete_binding => Expression[1])
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
def get_xrefs_x(dasm, di)
|
|
265
|
+
if di.opcode.props[:setip]
|
|
266
|
+
tg = di.instruction.args.last
|
|
267
|
+
case tg
|
|
268
|
+
when nil
|
|
269
|
+
raise 'internal error: no jmp target' if di.opcode.name != 'ret'
|
|
270
|
+
tg = :x30
|
|
271
|
+
when Expression
|
|
272
|
+
else tg = tg.symbolic
|
|
273
|
+
end
|
|
274
|
+
[tg]
|
|
275
|
+
else
|
|
276
|
+
# TODO ldr pc, ..
|
|
277
|
+
[]
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def backtrace_is_function_return(expr, di=nil)
|
|
282
|
+
expr.reduce_rec == :x30
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def backtrace_is_stack_address(expr)
|
|
286
|
+
Expression[expr].expr_externals.include? :sp
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|