metasm 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/BUGS +11 -0
- data/CREDITS +17 -0
- data/README +270 -0
- data/TODO +114 -0
- data/doc/code_organisation.txt +146 -0
- data/doc/const_missing.txt +16 -0
- data/doc/core_classes.txt +75 -0
- data/doc/feature_list.txt +53 -0
- data/doc/index.txt +59 -0
- data/doc/install_notes.txt +170 -0
- data/doc/style.css +3 -0
- data/doc/use_cases.txt +18 -0
- data/lib/metasm.rb +80 -0
- data/lib/metasm/arm.rb +12 -0
- data/lib/metasm/arm/debug.rb +39 -0
- data/lib/metasm/arm/decode.rb +167 -0
- data/lib/metasm/arm/encode.rb +77 -0
- data/lib/metasm/arm/main.rb +75 -0
- data/lib/metasm/arm/opcodes.rb +177 -0
- data/lib/metasm/arm/parse.rb +130 -0
- data/lib/metasm/arm/render.rb +55 -0
- data/lib/metasm/compile_c.rb +1457 -0
- data/lib/metasm/dalvik.rb +8 -0
- data/lib/metasm/dalvik/decode.rb +196 -0
- data/lib/metasm/dalvik/main.rb +60 -0
- data/lib/metasm/dalvik/opcodes.rb +366 -0
- data/lib/metasm/decode.rb +213 -0
- data/lib/metasm/decompile.rb +2659 -0
- data/lib/metasm/disassemble.rb +2068 -0
- data/lib/metasm/disassemble_api.rb +1280 -0
- data/lib/metasm/dynldr.rb +1329 -0
- data/lib/metasm/encode.rb +333 -0
- data/lib/metasm/exe_format/a_out.rb +194 -0
- data/lib/metasm/exe_format/autoexe.rb +82 -0
- data/lib/metasm/exe_format/bflt.rb +189 -0
- data/lib/metasm/exe_format/coff.rb +455 -0
- data/lib/metasm/exe_format/coff_decode.rb +901 -0
- data/lib/metasm/exe_format/coff_encode.rb +1078 -0
- data/lib/metasm/exe_format/dex.rb +457 -0
- data/lib/metasm/exe_format/dol.rb +145 -0
- data/lib/metasm/exe_format/elf.rb +923 -0
- data/lib/metasm/exe_format/elf_decode.rb +979 -0
- data/lib/metasm/exe_format/elf_encode.rb +1375 -0
- data/lib/metasm/exe_format/macho.rb +827 -0
- data/lib/metasm/exe_format/main.rb +228 -0
- data/lib/metasm/exe_format/mz.rb +164 -0
- data/lib/metasm/exe_format/nds.rb +172 -0
- data/lib/metasm/exe_format/pe.rb +437 -0
- data/lib/metasm/exe_format/serialstruct.rb +246 -0
- data/lib/metasm/exe_format/shellcode.rb +114 -0
- data/lib/metasm/exe_format/xcoff.rb +167 -0
- data/lib/metasm/gui.rb +23 -0
- data/lib/metasm/gui/cstruct.rb +373 -0
- data/lib/metasm/gui/dasm_coverage.rb +199 -0
- data/lib/metasm/gui/dasm_decomp.rb +369 -0
- data/lib/metasm/gui/dasm_funcgraph.rb +103 -0
- data/lib/metasm/gui/dasm_graph.rb +1354 -0
- data/lib/metasm/gui/dasm_hex.rb +543 -0
- data/lib/metasm/gui/dasm_listing.rb +599 -0
- data/lib/metasm/gui/dasm_main.rb +906 -0
- data/lib/metasm/gui/dasm_opcodes.rb +291 -0
- data/lib/metasm/gui/debug.rb +1228 -0
- data/lib/metasm/gui/gtk.rb +884 -0
- data/lib/metasm/gui/qt.rb +495 -0
- data/lib/metasm/gui/win32.rb +3004 -0
- data/lib/metasm/gui/x11.rb +621 -0
- data/lib/metasm/ia32.rb +14 -0
- data/lib/metasm/ia32/compile_c.rb +1523 -0
- data/lib/metasm/ia32/debug.rb +193 -0
- data/lib/metasm/ia32/decode.rb +1167 -0
- data/lib/metasm/ia32/decompile.rb +564 -0
- data/lib/metasm/ia32/encode.rb +314 -0
- data/lib/metasm/ia32/main.rb +233 -0
- data/lib/metasm/ia32/opcodes.rb +872 -0
- data/lib/metasm/ia32/parse.rb +327 -0
- data/lib/metasm/ia32/render.rb +91 -0
- data/lib/metasm/main.rb +1193 -0
- data/lib/metasm/mips.rb +11 -0
- data/lib/metasm/mips/compile_c.rb +7 -0
- data/lib/metasm/mips/decode.rb +253 -0
- data/lib/metasm/mips/encode.rb +51 -0
- data/lib/metasm/mips/main.rb +72 -0
- data/lib/metasm/mips/opcodes.rb +443 -0
- data/lib/metasm/mips/parse.rb +51 -0
- data/lib/metasm/mips/render.rb +43 -0
- data/lib/metasm/os/gnu_exports.rb +270 -0
- data/lib/metasm/os/linux.rb +1112 -0
- data/lib/metasm/os/main.rb +1686 -0
- data/lib/metasm/os/remote.rb +527 -0
- data/lib/metasm/os/windows.rb +2027 -0
- data/lib/metasm/os/windows_exports.rb +745 -0
- data/lib/metasm/parse.rb +876 -0
- data/lib/metasm/parse_c.rb +3938 -0
- data/lib/metasm/pic16c/decode.rb +42 -0
- data/lib/metasm/pic16c/main.rb +17 -0
- data/lib/metasm/pic16c/opcodes.rb +68 -0
- data/lib/metasm/ppc.rb +11 -0
- data/lib/metasm/ppc/decode.rb +264 -0
- data/lib/metasm/ppc/decompile.rb +251 -0
- data/lib/metasm/ppc/encode.rb +51 -0
- data/lib/metasm/ppc/main.rb +129 -0
- data/lib/metasm/ppc/opcodes.rb +410 -0
- data/lib/metasm/ppc/parse.rb +52 -0
- data/lib/metasm/preprocessor.rb +1277 -0
- data/lib/metasm/render.rb +130 -0
- data/lib/metasm/sh4.rb +8 -0
- data/lib/metasm/sh4/decode.rb +336 -0
- data/lib/metasm/sh4/main.rb +292 -0
- data/lib/metasm/sh4/opcodes.rb +381 -0
- data/lib/metasm/x86_64.rb +12 -0
- data/lib/metasm/x86_64/compile_c.rb +1025 -0
- data/lib/metasm/x86_64/debug.rb +59 -0
- data/lib/metasm/x86_64/decode.rb +268 -0
- data/lib/metasm/x86_64/encode.rb +264 -0
- data/lib/metasm/x86_64/main.rb +135 -0
- data/lib/metasm/x86_64/opcodes.rb +118 -0
- data/lib/metasm/x86_64/parse.rb +68 -0
- data/misc/bottleneck.rb +61 -0
- data/misc/cheader-findpppath.rb +58 -0
- data/misc/hexdiff.rb +74 -0
- data/misc/hexdump.rb +55 -0
- data/misc/metasm-all.rb +13 -0
- data/misc/objdiff.rb +47 -0
- data/misc/objscan.rb +40 -0
- data/misc/pdfparse.rb +661 -0
- data/misc/ppc_pdf2oplist.rb +192 -0
- data/misc/tcp_proxy_hex.rb +84 -0
- data/misc/txt2html.rb +440 -0
- data/samples/a.out.rb +31 -0
- data/samples/asmsyntax.rb +77 -0
- data/samples/bindiff.rb +555 -0
- data/samples/compilation-steps.rb +49 -0
- data/samples/cparser_makestackoffset.rb +55 -0
- data/samples/dasm-backtrack.rb +38 -0
- data/samples/dasmnavig.rb +318 -0
- data/samples/dbg-apihook.rb +228 -0
- data/samples/dbghelp.rb +143 -0
- data/samples/disassemble-gui.rb +102 -0
- data/samples/disassemble.rb +133 -0
- data/samples/dump_upx.rb +95 -0
- data/samples/dynamic_ruby.rb +1929 -0
- data/samples/elf_list_needed.rb +46 -0
- data/samples/elf_listexports.rb +33 -0
- data/samples/elfencode.rb +25 -0
- data/samples/exeencode.rb +128 -0
- data/samples/factorize-headers-elfimports.rb +77 -0
- data/samples/factorize-headers-peimports.rb +109 -0
- data/samples/factorize-headers.rb +43 -0
- data/samples/gdbclient.rb +583 -0
- data/samples/generate_libsigs.rb +102 -0
- data/samples/hotfix_gtk_dbg.rb +59 -0
- data/samples/install_win_env.rb +78 -0
- data/samples/lindebug.rb +924 -0
- data/samples/linux_injectsyscall.rb +95 -0
- data/samples/machoencode.rb +31 -0
- data/samples/metasm-shell.rb +91 -0
- data/samples/pe-hook.rb +69 -0
- data/samples/pe-ia32-cpuid.rb +203 -0
- data/samples/pe-mips.rb +35 -0
- data/samples/pe-shutdown.rb +78 -0
- data/samples/pe-testrelocs.rb +51 -0
- data/samples/pe-testrsrc.rb +24 -0
- data/samples/pe_listexports.rb +31 -0
- data/samples/peencode.rb +19 -0
- data/samples/peldr.rb +494 -0
- data/samples/preprocess-flatten.rb +19 -0
- data/samples/r0trace.rb +308 -0
- data/samples/rubstop.rb +399 -0
- data/samples/scan_pt_gnu_stack.rb +54 -0
- data/samples/scanpeexports.rb +62 -0
- data/samples/shellcode-c.rb +40 -0
- data/samples/shellcode-dynlink.rb +146 -0
- data/samples/source.asm +34 -0
- data/samples/struct_offset.rb +47 -0
- data/samples/testpe.rb +32 -0
- data/samples/testraw.rb +45 -0
- data/samples/win32genloader.rb +132 -0
- data/samples/win32hooker-advanced.rb +169 -0
- data/samples/win32hooker.rb +96 -0
- data/samples/win32livedasm.rb +33 -0
- data/samples/win32remotescan.rb +133 -0
- data/samples/wintrace.rb +92 -0
- data/tests/all.rb +8 -0
- data/tests/dasm.rb +39 -0
- data/tests/dynldr.rb +35 -0
- data/tests/encodeddata.rb +132 -0
- data/tests/ia32.rb +82 -0
- data/tests/mips.rb +116 -0
- data/tests/parse_c.rb +239 -0
- data/tests/preprocessor.rb +269 -0
- data/tests/x86_64.rb +62 -0
- metadata +255 -0
data/lib/metasm/arm.rb
ADDED
@@ -0,0 +1,12 @@
|
|
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
|
+
require 'metasm/arm/parse'
|
9
|
+
require 'metasm/arm/encode'
|
10
|
+
require 'metasm/arm/decode'
|
11
|
+
require 'metasm/arm/render'
|
12
|
+
require 'metasm/arm/debug'
|
@@ -0,0 +1,39 @@
|
|
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/arm/opcodes'
|
8
|
+
|
9
|
+
module Metasm
|
10
|
+
class ARM
|
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 ||= [:r0, :r1, :r2, :r3, :r4, :r5, :r6, :r7, :r8, :r9, :r10, :r11, :r12, :sp, :lr, :pc]
|
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(32)
|
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' # TODO
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,167 @@
|
|
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/arm/opcodes'
|
7
|
+
require 'metasm/decode'
|
8
|
+
|
9
|
+
module Metasm
|
10
|
+
class ARM
|
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 >> 20) & 0xff
|
29
|
+
msk = (op.bin_mask >> 20) & 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 >= edata.data.length
|
42
|
+
di = DecodedInstruction.new(self)
|
43
|
+
val = edata.decode_imm(:u32, @endianness)
|
44
|
+
di.instance_variable_set('@raw', val)
|
45
|
+
di if di.opcode = @bin_lookaside[(val >> 20) & 0xff].find { |op|
|
46
|
+
(not op.props[:cond] or
|
47
|
+
((val >> @fields_shift[:cond]) & @fields_mask[:cond]) != 0xf) and
|
48
|
+
(op.bin & op.bin_mask) == (val & op.bin_mask)
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
def disassembler_default_func
|
53
|
+
df = DecodedFunction.new
|
54
|
+
df
|
55
|
+
end
|
56
|
+
|
57
|
+
def decode_instr_op(edata, di)
|
58
|
+
op = di.opcode
|
59
|
+
di.instruction.opname = op.name
|
60
|
+
val = di.instance_variable_get('@raw')
|
61
|
+
|
62
|
+
field_val = lambda { |f|
|
63
|
+
r = (val >> @fields_shift[f]) & @fields_mask[f]
|
64
|
+
case f
|
65
|
+
when :i16; Expression.make_signed(r, 16)
|
66
|
+
when :i24; Expression.make_signed(r, 24)
|
67
|
+
when :i8_12; ((r >> 4) & 0xf0) | (r & 0xf)
|
68
|
+
when :stype; [:lsl, :lsr, :asr, :ror][r]
|
69
|
+
when :u; [:-, :+][r]
|
70
|
+
else r
|
71
|
+
end
|
72
|
+
}
|
73
|
+
|
74
|
+
if op.props[:cond]
|
75
|
+
cd = %w[eq ne cs cc mi pl vs vc hi ls ge lt gt le al][field_val[:cond]]
|
76
|
+
if cd != 'al'
|
77
|
+
di.opcode = di.opcode.dup
|
78
|
+
di.instruction.opname = di.opcode.name.dup
|
79
|
+
di.instruction.opname[(op.props[:cond_name_off] || di.opcode.name.length), 0] = cd
|
80
|
+
if di.opcode.props[:stopexec]
|
81
|
+
di.opcode.props = di.opcode.props.dup
|
82
|
+
di.opcode.props.delete :stopexec
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
op.args.each { |a|
|
88
|
+
di.instruction.args << case a
|
89
|
+
when :rd, :rn, :rm; Reg.new field_val[a]
|
90
|
+
when :rm_rs; Reg.new field_val[:rm], field_val[:stype], Reg.new(field_val[:rs])
|
91
|
+
when :rm_is; Reg.new field_val[:rm], field_val[:stype], field_val[:shifti]*2
|
92
|
+
when :i24; Expression[field_val[a] << 2]
|
93
|
+
when :i8_r
|
94
|
+
i = field_val[:i8]
|
95
|
+
r = field_val[:rotate]*2
|
96
|
+
Expression[((i >> r) | (i << (32-r))) & 0xffff_ffff]
|
97
|
+
when :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12
|
98
|
+
b = Reg.new(field_val[:rn])
|
99
|
+
o = case a
|
100
|
+
when :mem_rn_rm; Reg.new(field_val[:rm])
|
101
|
+
when :mem_rn_i8_12; field_val[:i8_12]
|
102
|
+
when :mem_rn_rms; Reg.new(field_val[:rm], field_val[:stype], field_val[:shifti]*2)
|
103
|
+
when :mem_rn_i12; field_val[:i12]
|
104
|
+
end
|
105
|
+
Memref.new(b, o, field_val[:u], op.props[:baseincr])
|
106
|
+
when :reglist
|
107
|
+
di.instruction.args.last.updated = true if op.props[:baseincr]
|
108
|
+
msk = field_val[a]
|
109
|
+
l = RegList.new((0..15).map { |i| Reg.new(i) if (msk & (1 << i)) > 0 }.compact)
|
110
|
+
l.usermoderegs = true if op.props[:usermoderegs]
|
111
|
+
l
|
112
|
+
else raise SyntaxError, "Internal error: invalid argument #{a} in #{op.name}"
|
113
|
+
end
|
114
|
+
}
|
115
|
+
|
116
|
+
di.bin_length = 4
|
117
|
+
di
|
118
|
+
end
|
119
|
+
|
120
|
+
def decode_instr_interpret(di, addr)
|
121
|
+
if di.opcode.args.include? :i24
|
122
|
+
di.instruction.args[-1] = Expression[di.instruction.args[-1] + addr + 8]
|
123
|
+
end
|
124
|
+
di
|
125
|
+
end
|
126
|
+
|
127
|
+
def backtrace_binding
|
128
|
+
@backtrace_binding ||= init_backtrace_binding
|
129
|
+
end
|
130
|
+
|
131
|
+
def init_backtrace_binding
|
132
|
+
@backtrace_binding ||= {}
|
133
|
+
end
|
134
|
+
|
135
|
+
def get_backtrace_binding(di)
|
136
|
+
a = di.instruction.args.map { |arg|
|
137
|
+
case arg
|
138
|
+
when Reg; arg.symbolic
|
139
|
+
when Memref; arg.symbolic(di.address)
|
140
|
+
else arg
|
141
|
+
end
|
142
|
+
}
|
143
|
+
|
144
|
+
if binding = backtrace_binding[di.opcode.name]
|
145
|
+
bd = binding[di, *a]
|
146
|
+
else
|
147
|
+
puts "unhandled instruction to backtrace: #{di}" if $VERBOSE
|
148
|
+
# assume nothing except the 1st arg is modified
|
149
|
+
case a[0]
|
150
|
+
when Indirection, Symbol; { a[0] => Expression::Unknown }
|
151
|
+
when Expression; (x = a[0].externals.first) ? { x => Expression::Unknown } : {}
|
152
|
+
else {}
|
153
|
+
end.update(:incomplete_binding => Expression[1])
|
154
|
+
end
|
155
|
+
|
156
|
+
end
|
157
|
+
|
158
|
+
def get_xrefs_x(dasm, di)
|
159
|
+
if di.opcode.props[:setip]
|
160
|
+
[di.instruction.args.last]
|
161
|
+
else
|
162
|
+
# TODO ldr pc, ..
|
163
|
+
[]
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
@@ -0,0 +1,77 @@
|
|
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/arm/opcodes'
|
8
|
+
require 'metasm/encode'
|
9
|
+
|
10
|
+
module Metasm
|
11
|
+
class ARM
|
12
|
+
def encode_instr_op(section, instr, op)
|
13
|
+
base = op.bin
|
14
|
+
set_field = lambda { |f, v|
|
15
|
+
v = v.reduce if v.kind_of? Expression
|
16
|
+
case f
|
17
|
+
when :i8_12
|
18
|
+
base = Expression[base, :|, [[v, :&, 0xf], :|, [[v, :<<, 4], :&, 0xf00]]]
|
19
|
+
next
|
20
|
+
when :stype; v = [:lsl, :lsr, :asr, :ror].index(v)
|
21
|
+
when :u; v = [:-, :+].index(v)
|
22
|
+
end
|
23
|
+
base = Expression[base, :|, [[v, :&, @fields_mask[f]], :<<, @fields_shift[f]]]
|
24
|
+
}
|
25
|
+
|
26
|
+
val, mask, shift = 0, 0, 0
|
27
|
+
|
28
|
+
if op.props[:cond]
|
29
|
+
coff = op.props[:cond_name_off] || op.name.length
|
30
|
+
cd = instr.opname[coff, 2]
|
31
|
+
cdi = %w[eq ne cs cc mi pl vs vc hi ls ge lt gt le al].index(cd) || 14 # default = al
|
32
|
+
set_field[:cond, cdi]
|
33
|
+
end
|
34
|
+
|
35
|
+
op.args.zip(instr.args).each { |sym, arg|
|
36
|
+
case sym
|
37
|
+
when :rd, :rs, :rn, :rm; set_field[sym, arg.i]
|
38
|
+
when :rm_rs
|
39
|
+
set_field[:rm, arg.i]
|
40
|
+
set_field[:stype, arg.stype]
|
41
|
+
set_field[:rs, arg.shift.i]
|
42
|
+
when :rm_is
|
43
|
+
set_field[:rm, arg.i]
|
44
|
+
set_field[:stype, arg.stype]
|
45
|
+
set_field[:shifti, arg.shift/2]
|
46
|
+
when :mem_rn_rm, :mem_rn_rms, :mem_rn_i8_12, :mem_rn_i12
|
47
|
+
set_field[:rn, arg.base.i]
|
48
|
+
case sym
|
49
|
+
when :mem_rn_rm
|
50
|
+
set_field[:rm, arg.offset.i]
|
51
|
+
when :mem_rn_rms
|
52
|
+
set_field[:rm, arg.offset.i]
|
53
|
+
set_field[:stype, arg.offset.stype]
|
54
|
+
set_field[:rs, arg.offset.shift.i]
|
55
|
+
when :mem_rn_i8_12
|
56
|
+
set_field[:i8_12, arg.offset]
|
57
|
+
when :mem_rn_i12
|
58
|
+
set_field[:i12, arg.offset]
|
59
|
+
end
|
60
|
+
# TODO set_field[:u] etc
|
61
|
+
when :reglist
|
62
|
+
set_field[sym, arg.list.inject(0) { |rl, r| rl | (1 << r.i) }]
|
63
|
+
when :i8_r
|
64
|
+
# XXX doublecheck this
|
65
|
+
b = arg.reduce & 0xffffffff
|
66
|
+
r = (0..15).find { next true if b < 0x10 ; b = (b >> 2) | ((b & 3) << 30) }
|
67
|
+
set_field[:i8, b]
|
68
|
+
set_field[:rotate, r]
|
69
|
+
when :i16, :i24
|
70
|
+
val, mask, shift = arg, @fields_mask[sym], @fields_shift[sym]
|
71
|
+
end
|
72
|
+
}
|
73
|
+
|
74
|
+
Expression[base, :|, [[val, :<<, shift], :&, mask]].encode(:u32, @endianness)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,75 @@
|
|
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 ARM < CPU
|
11
|
+
class Reg
|
12
|
+
class << self
|
13
|
+
attr_accessor :s_to_i, :i_to_s
|
14
|
+
end
|
15
|
+
@i_to_s = %w[r0 r1 r2 r3 r4 r5 r6 r7 r8 r9 r10 r11 r12 sp lr pc]
|
16
|
+
@s_to_i = { 'wr' => 7, 'sb' => 9, 'sl' => 10, 'fp' => 11, 'ip' => 12, 'sp' => 13, 'lr' => 14, 'pc' => 15 }
|
17
|
+
15.times { |i| @s_to_i["r#{i}"] = i }
|
18
|
+
4.times { |i| @s_to_i["a#{i+1}"] = i }
|
19
|
+
8.times { |i| @s_to_i["v#{i+1}"] = i+4 }
|
20
|
+
|
21
|
+
attr_accessor :i, :stype, :shift, :updated
|
22
|
+
def initialize(i, stype=:lsl, shift=0)
|
23
|
+
@i = i
|
24
|
+
@stype = stype
|
25
|
+
@shift = shift
|
26
|
+
end
|
27
|
+
|
28
|
+
def symbolic
|
29
|
+
r = self.class.i_to_s[@i].to_sym
|
30
|
+
if @stype == :lsl and @shift == 0
|
31
|
+
r
|
32
|
+
else
|
33
|
+
r # TODO shift/rotate/...
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class Memref
|
39
|
+
attr_accessor :base, :offset, :sign, :incr
|
40
|
+
def initialize(base, offset, sign=:+, incr=nil)
|
41
|
+
@base, @offset, @sign, @incr = base, offset, sign, incr
|
42
|
+
end
|
43
|
+
|
44
|
+
def symbolic(len=4, orig=nil)
|
45
|
+
o = @offset
|
46
|
+
o = o.symbolic if o.kind_of? Reg
|
47
|
+
p = Expression[@base.symbolic, @sign, o].reduce
|
48
|
+
Indirection[p, len, orig]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class RegList
|
53
|
+
attr_accessor :list, :usermoderegs
|
54
|
+
|
55
|
+
def initialize(l=[])
|
56
|
+
@list = l
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def initialize(endianness = :little)
|
61
|
+
super()
|
62
|
+
@endianness = endianness
|
63
|
+
@size = 32
|
64
|
+
end
|
65
|
+
|
66
|
+
def init_opcode_list
|
67
|
+
init_latest
|
68
|
+
@opcode_list
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class ARM_THUMB < ARM
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
@@ -0,0 +1,177 @@
|
|
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/arm/main'
|
8
|
+
|
9
|
+
module Metasm
|
10
|
+
class ARM
|
11
|
+
private
|
12
|
+
def addop(name, bin, *args)
|
13
|
+
args << :cond if not args.delete :uncond
|
14
|
+
|
15
|
+
o = Opcode.new name, bin
|
16
|
+
o.args.concat(args & @valid_args)
|
17
|
+
(args & @valid_props).each { |p| o.props[p] = true }
|
18
|
+
args.grep(Hash).each { |h| o.props.update h }
|
19
|
+
|
20
|
+
# special args -> multiple fields
|
21
|
+
case (o.args & [:i8_r, :rm_is, :rm_rs, :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12]).first
|
22
|
+
when :i8_r; args << :i8 << :rotate
|
23
|
+
when :rm_is; args << :rm << :stype << :shifti
|
24
|
+
when :rm_rs; args << :rm << :stype << :rs
|
25
|
+
when :mem_rn_rm; args << :rn << :rm << :rsx << :u
|
26
|
+
when :mem_rn_i8_12; args << :rn << :i8_12 << :u
|
27
|
+
when :mem_rn_rms; args << :rn << :rm << :stype << :shifti << :u
|
28
|
+
when :mem_rn_i12; args << :rn << :i12 << :u
|
29
|
+
end
|
30
|
+
|
31
|
+
(args & @fields_mask.keys).each { |f|
|
32
|
+
o.fields[f] = [@fields_mask[f], @fields_shift[f]]
|
33
|
+
}
|
34
|
+
|
35
|
+
@opcode_list << o
|
36
|
+
end
|
37
|
+
|
38
|
+
def addop_data_s(name, op, a1, a2, *h)
|
39
|
+
addop name, op | (1 << 25), a1, a2, :i8_r, :rotate, *h
|
40
|
+
addop name, op, a1, a2, :rm_is, *h
|
41
|
+
addop name, op | (1 << 4), a1, a2, :rm_rs, *h
|
42
|
+
end
|
43
|
+
def addop_data(name, op, a1, a2)
|
44
|
+
addop_data_s name, op << 21, a1, a2
|
45
|
+
addop_data_s name+'s', (op << 21) | (1 << 20), a1, a2, :cond_name_off => name.length
|
46
|
+
end
|
47
|
+
|
48
|
+
def addop_load_puw(name, op, *a)
|
49
|
+
addop name, op, {:baseincr => :post}, :rd, :u, *a
|
50
|
+
addop name, op | (1 << 24), :rd, :u, *a
|
51
|
+
addop name, op | (1 << 24) | (1 << 21), {:baseincr => :pre}, :rd, :u, *a
|
52
|
+
end
|
53
|
+
def addop_load_lsh_o(name, op)
|
54
|
+
addop_load_puw name, op, :rsz, :mem_rn_rm, {:cond_name_off => 3}
|
55
|
+
addop_load_puw name, op | (1 << 22), :mem_rn_i8_12, {:cond_name_off => 3}
|
56
|
+
end
|
57
|
+
def addop_load_lsh
|
58
|
+
op = 9 << 4
|
59
|
+
addop_load_lsh_o 'strh', op | (1 << 5)
|
60
|
+
addop_load_lsh_o 'ldrd', op | (1 << 6)
|
61
|
+
addop_load_lsh_o 'strd', op | (1 << 6) | (1 << 5)
|
62
|
+
addop_load_lsh_o 'ldrh', op | (1 << 20) | (1 << 5)
|
63
|
+
addop_load_lsh_o 'ldrsb', op | (1 << 20) | (1 << 6)
|
64
|
+
addop_load_lsh_o 'ldrsh', op | (1 << 20) | (1 << 6) | (1 << 5)
|
65
|
+
end
|
66
|
+
|
67
|
+
def addop_load_puwt(name, op, *a)
|
68
|
+
addop_load_puw name, op, *a
|
69
|
+
addop name+'t', op | (1 << 21), {:baseincr => :post, :cond_name_off => name.length}, :rd, :u, *a
|
70
|
+
end
|
71
|
+
def addop_load_o(name, op, *a)
|
72
|
+
addop_load_puwt name, op, :mem_rn_i12, *a
|
73
|
+
addop_load_puwt name, op | (1 << 25), :mem_rn_rms, *a
|
74
|
+
end
|
75
|
+
def addop_load(name, op)
|
76
|
+
addop_load_o name, op
|
77
|
+
addop_load_o name+'b', op | (1 << 22), :cond_name_off => name.length
|
78
|
+
end
|
79
|
+
|
80
|
+
def addop_ldm_go(name, op, *a)
|
81
|
+
addop name, op, :rn, :reglist, {:cond_name_off => 3}, *a
|
82
|
+
end
|
83
|
+
def addop_ldm_w(name, op, *a)
|
84
|
+
addop_ldm_go name, op, *a # base reg untouched
|
85
|
+
addop_ldm_go name, op | (1 << 21), {:baseincr => :post}, *a # base updated
|
86
|
+
end
|
87
|
+
def addop_ldm_s(name, op)
|
88
|
+
addop_ldm_w name, op # transfer regs
|
89
|
+
addop_ldm_w name, op | (1 << 22), :usermoderegs # transfer usermode regs
|
90
|
+
end
|
91
|
+
def addop_ldm_p(name, op)
|
92
|
+
addop_ldm_s name+'a', op # target memory included
|
93
|
+
addop_ldm_s name+'b', op | (1 << 24) # target memory excluded, transfer starts at next addr
|
94
|
+
end
|
95
|
+
def addop_ldm_u(name, op)
|
96
|
+
addop_ldm_p name+'d', op # transfer made downward
|
97
|
+
addop_ldm_p name+'i', op | (1 << 23) # transfer made upward
|
98
|
+
end
|
99
|
+
def addop_ldm(name, op)
|
100
|
+
addop_ldm_u name, op
|
101
|
+
end
|
102
|
+
|
103
|
+
# ARMv6 instruction set, aka arm7/arm9
|
104
|
+
def init_arm_v6
|
105
|
+
@opcode_list = []
|
106
|
+
@valid_props << :baseincr << :cond << :cond_name_off << :usermoderegs <<
|
107
|
+
:tothumb << :tojazelle
|
108
|
+
@valid_args.concat [:rn, :rd, :rm, :crn, :crd, :crm, :cpn, :reglist, :i24,
|
109
|
+
:rm_rs, :rm_is, :i8_r, :mem_rn_rm, :mem_rn_i8_12, :mem_rn_rms, :mem_rn_i12]
|
110
|
+
@fields_mask.update :rn => 0xf, :rd => 0xf, :rs => 0xf, :rm => 0xf,
|
111
|
+
:crn => 0xf, :crd => 0xf, :crm => 0xf, :cpn => 0xf,
|
112
|
+
:rnx => 0xf, :rdx => 0xf, :rsx => 0xf,
|
113
|
+
:shifti => 0x1f, :stype => 3, :rotate => 0xf, :reglist => 0xffff,
|
114
|
+
:i8 => 0xff, :i12 => 0xfff, :i24 => 0xff_ffff, :i8_12 => 0xf0f,
|
115
|
+
:u => 1, :mask => 0xf, :sbo => 0xf, :cond => 0xf
|
116
|
+
|
117
|
+
@fields_shift.update :rn => 16, :rd => 12, :rs => 8, :rm => 0,
|
118
|
+
:crn => 16, :crd => 12, :crm => 0, :cpn => 8,
|
119
|
+
:rnx => 16, :rdx => 12, :rsx => 8,
|
120
|
+
:shifti => 7, :stype => 5, :rotate => 8, :reglist => 0,
|
121
|
+
:i8 => 0, :i12 => 0, :i24 => 0, :i8_12 => 0,
|
122
|
+
:u => 23, :mask => 16, :sbo => 12, :cond => 28
|
123
|
+
|
124
|
+
addop_data 'and', 0, :rd, :rn
|
125
|
+
addop_data 'eor', 1, :rd, :rn
|
126
|
+
addop_data 'xor', 1, :rd, :rn
|
127
|
+
addop_data 'sub', 2, :rd, :rn
|
128
|
+
addop_data 'rsb', 3, :rd, :rn
|
129
|
+
addop_data 'add', 4, :rd, :rn
|
130
|
+
addop_data 'adc', 5, :rd, :rn
|
131
|
+
addop_data 'sbc', 6, :rd, :rn
|
132
|
+
addop_data 'rsc', 7, :rd, :rn
|
133
|
+
addop_data 'tst', 8, :rdx, :rn
|
134
|
+
addop_data 'teq', 9, :rdx, :rn
|
135
|
+
addop_data 'cmp', 10, :rdx, :rn
|
136
|
+
addop_data 'cmn', 11, :rdx, :rn
|
137
|
+
addop_data 'orr', 12, :rd, :rn
|
138
|
+
addop_data 'or', 12, :rd, :rn
|
139
|
+
addop_data 'mov', 13, :rd, :rnx
|
140
|
+
addop_data 'bic', 14, :rd, :rn
|
141
|
+
addop_data 'mvn', 15, :rd, :rnx
|
142
|
+
|
143
|
+
addop 'b', 0b1010 << 24, :setip, :stopexec, :i24
|
144
|
+
addop 'bl', 0b1011 << 24, :setip, :stopexec, :i24, :saveip
|
145
|
+
addop 'bkpt', (0b00010010 << 20) | (0b0111 << 4) # other fields are available&unused, also cnd != AL is undef
|
146
|
+
addop 'blx', 0b1111101 << 25, :setip, :stopexec, :saveip, :tothumb, :h, :nocond, :i24
|
147
|
+
addop 'blx', (0b00010010 << 20) | (0b0011 << 4), :setip, :stopexec, :saveip, :tothumb, :rm
|
148
|
+
addop 'bx', (0b00010010 << 20) | (0b0001 << 4), :setip, :stopexec, :rm
|
149
|
+
addop 'bxj', (0b00010010 << 20) | (0b0010 << 4), :setip, :stopexec, :rm, :tojazelle
|
150
|
+
|
151
|
+
addop_load 'str', (1 << 26)
|
152
|
+
addop_load 'ldr', (1 << 26) | (1 << 20)
|
153
|
+
addop_load_lsh
|
154
|
+
addop_ldm 'stm', (1 << 27)
|
155
|
+
addop_ldm 'ldm', (1 << 27) | (1 << 20)
|
156
|
+
end
|
157
|
+
alias init_latest init_arm_v6
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
__END__
|
162
|
+
addop_cond 'mrs', 0b0001000011110000000000000000, :rd
|
163
|
+
addop_cond 'msr', 0b0001001010011111000000000000, :rd
|
164
|
+
addop_cond 'msrf', 0b0001001010001111000000000000, :rd
|
165
|
+
|
166
|
+
addop_cond 'mul', 0b000000000000001001 << 4, :rd, :rn, :rs, :rm
|
167
|
+
addop_cond 'mla', 0b100000000000001001 << 4, :rd, :rn, :rs, :rm
|
168
|
+
|
169
|
+
addop_cond 'swp', 0b0001000000000000000010010000, :rd, :rn, :rs, :rm
|
170
|
+
addop_cond 'swpb', 0b0001010000000000000010010000, :rd, :rn, :rs, :rm
|
171
|
+
|
172
|
+
addop_cond 'undef', 0b00000110000000000000000000010000
|
173
|
+
|
174
|
+
addop_cond 'swi', 0b00001111 << 24
|
175
|
+
|
176
|
+
addop_cond 'bkpt', 0b1001000000000000001110000
|
177
|
+
addop_cond 'movw', 0b0011 << 24, :movwimm
|