metasm 1.0.2 → 1.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/Gemfile +1 -0
- data/doc/code_organisation.txt +1 -1
- data/metasm.gemspec +1 -1
- data/metasm.rb +2 -1
- data/metasm/cpu/arc/decode.rb +3 -3
- data/metasm/cpu/arm/decode.rb +2 -2
- data/metasm/cpu/ia32/compile_c.rb +18 -2
- data/metasm/cpu/ia32/decode.rb +9 -4
- data/metasm/cpu/ia32/decompile.rb +22 -8
- data/metasm/cpu/ia32/opcodes.rb +5 -5
- data/metasm/cpu/mcs51.rb +8 -0
- data/metasm/cpu/mcs51/decode.rb +99 -0
- data/metasm/cpu/mcs51/main.rb +76 -0
- data/metasm/cpu/mcs51/opcodes.rb +120 -0
- data/metasm/cpu/mips/decode.rb +5 -4
- data/metasm/cpu/st20.rb +9 -0
- data/metasm/cpu/st20/decode.rb +180 -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/metasm/cpu/x86_64/encode.rb +4 -2
- data/metasm/cpu/x86_64/opcodes.rb +4 -2
- data/metasm/decode.rb +16 -15
- data/metasm/decompile.rb +1 -1
- data/metasm/disassemble.rb +3 -1
- data/metasm/disassemble_api.rb +3 -1
- data/metasm/dynldr.rb +9 -3
- data/metasm/encode.rb +2 -2
- data/metasm/exe_format/coff.rb +3 -1
- data/metasm/exe_format/coff_decode.rb +5 -3
- data/metasm/exe_format/elf.rb +4 -0
- data/metasm/exe_format/elf_decode.rb +1 -2
- data/metasm/exe_format/elf_encode.rb +4 -1
- data/metasm/exe_format/macho.rb +20 -6
- data/metasm/exe_format/pe.rb +1 -1
- data/metasm/exe_format/serialstruct.rb +1 -1
- data/metasm/gui.rb +1 -1
- data/metasm/gui/dasm_hex.rb +2 -2
- data/metasm/gui/dasm_main.rb +8 -8
- data/metasm/gui/debug.rb +4 -4
- data/metasm/gui/gtk.rb +1 -1
- data/metasm/gui/qt.rb +2 -2
- data/metasm/gui/win32.rb +1 -1
- data/metasm/main.rb +11 -6
- data/metasm/os/windows.rb +26 -23
- data/misc/hexdump.rb +2 -2
- data/misc/objdiff.rb +4 -1
- data/misc/objscan.rb +1 -1
- data/samples/dasm-plugins/bindiff.rb +1 -1
- data/samples/dasm-plugins/scanxrefs.rb +2 -1
- data/samples/dynamic_ruby.rb +24 -25
- data/samples/elfencode.rb +15 -0
- data/samples/exeencode.rb +2 -2
- data/samples/metasm-shell.rb +67 -55
- data/tests/mcs51.rb +27 -0
- metadata +13 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8a5dcb50d2a38105adee7c8249698e2f675af544
|
4
|
+
data.tar.gz: 0476236904d2bc2b8d45013446a58d053f0f24aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad41d74f97fab2567509acddb90ea7124c317519e84af509c6e68d07839ff1015a2c4512286e76eb16db22efa481aa60531beeb66e5ec9c0677727ba6cf81571
|
7
|
+
data.tar.gz: 333a45fd258674ead5f2b036e56e8e87ad06b4aa74b5f655495d05b902394527dad0abf78e614c7d6f715caa3d92c05b322166bfed74fb611ad3ddabbd4f7a1c
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/doc/code_organisation.txt
CHANGED
@@ -107,7 +107,7 @@ The actual implementation of the GUI are found in:
|
|
107
107
|
|
108
108
|
Please note that the Qt backend does not work *at all*.
|
109
109
|
|
110
|
-
The `gui.rb` file in the main directory is used to
|
110
|
+
The `gui.rb` file in the main directory is used to choose among the available GUI backend
|
111
111
|
the most appropriate for the current session.
|
112
112
|
|
113
113
|
|
data/metasm.gemspec
CHANGED
data/metasm.rb
CHANGED
@@ -16,6 +16,7 @@ module Metasm
|
|
16
16
|
'X86' => 'Ia32', 'PPC' => 'PowerPC',
|
17
17
|
'X64' => 'X86_64', 'AMD64' => 'X86_64',
|
18
18
|
'MIPS64' => 'MIPS', 'AArch64' => 'ARM64',
|
19
|
+
'TransPuter' => 'ST20',
|
19
20
|
'UniversalBinary' => 'MachO', 'COFFArchive' => 'COFF',
|
20
21
|
'DEY' => 'DEX',
|
21
22
|
'PTrace' => 'LinOS', 'FatELF' => 'ELF',
|
@@ -36,7 +37,7 @@ module Metasm
|
|
36
37
|
'Ia32' => 'cpu/ia32', 'MIPS' => 'cpu/mips', 'PowerPC' => 'cpu/ppc', 'ARM' => 'cpu/arm',
|
37
38
|
'X86_64' => 'cpu/x86_64', 'Sh4' => 'cpu/sh4', 'Dalvik' => 'cpu/dalvik', 'ARC' => 'cpu/arc',
|
38
39
|
'Python' => 'cpu/python', 'Z80' => 'cpu/z80', 'CY16' => 'cpu/cy16', 'BPF' => 'cpu/bpf',
|
39
|
-
'MSP430' => 'cpu/msp430', 'ARM64' => 'cpu/arm64',
|
40
|
+
'MSP430' => 'cpu/msp430', 'ARM64' => 'cpu/arm64', 'ST20' => 'cpu/st20', 'MCS51' => 'cpu/mcs51',
|
40
41
|
'C' => 'compile_c',
|
41
42
|
'MZ' => 'exe_format/mz', 'PE' => 'exe_format/pe',
|
42
43
|
'ELF' => 'exe_format/elf', 'COFF' => 'exe_format/coff',
|
data/metasm/cpu/arc/decode.rb
CHANGED
@@ -79,7 +79,7 @@ class ARC
|
|
79
79
|
lookaside = lookaside[sub_opcode(val)] if @instrlength == 32 and maj == 5
|
80
80
|
|
81
81
|
op = lookaside.select { |opcode|
|
82
|
-
if
|
82
|
+
if false and (val & opcode.bin_mask) == opcode.bin
|
83
83
|
puts "#{opcode.bin_mask.to_s(16)} - #{opcode.bin.to_s(16)} - #{(val & opcode.bin_mask).to_s(16)} - #{opcode.name} - #{opcode.args}"
|
84
84
|
end
|
85
85
|
(val & opcode.bin_mask) == opcode.bin
|
@@ -255,7 +255,7 @@ class ARC
|
|
255
255
|
tmp = field_val[a]
|
256
256
|
#c = tmp & 0x3F
|
257
257
|
tmp = tmp >> 6
|
258
|
-
b = (tmp >> 12) | ((tmp & 0x7) << 3)
|
258
|
+
#b = (tmp >> 12) | ((tmp & 0x7) << 3)
|
259
259
|
Memref.new(field_val[:bext], field_val[:cext], memref_size(di))
|
260
260
|
|
261
261
|
when :u6, :u6e, :s8e, :s9, :s12; Expression[field_val[a]]
|
@@ -263,7 +263,7 @@ class ARC
|
|
263
263
|
when :auxs12; AUX.new field_val[:s12]
|
264
264
|
when :@c; Memref.new(GPR.new(field_val[a]), nil, memref_size(di))
|
265
265
|
when :@bcext; Memref.new(field_val[a], nil, memref_size(di))
|
266
|
-
when :@bcext; Memref.new(field_val[:b], field_val[:cext], memref_size(di))
|
266
|
+
#when :@bcext; Memref.new(field_val[:b], field_val[:cext], memref_size(di))
|
267
267
|
when :@bs9
|
268
268
|
# [b,s9] or [limm] if b = 0x3E
|
269
269
|
base = field_val[:bext]
|
data/metasm/cpu/arm/decode.rb
CHANGED
@@ -41,7 +41,7 @@ class ARM
|
|
41
41
|
return if edata.ptr+4 > edata.length
|
42
42
|
di = DecodedInstruction.new(self)
|
43
43
|
val = edata.decode_imm(:u32, @endianness)
|
44
|
-
di.
|
44
|
+
di.misc = val
|
45
45
|
di if di.opcode = @bin_lookaside[(val >> 20) & 0xff].find { |op|
|
46
46
|
(not op.props[:cond] or
|
47
47
|
((val >> @fields_shift[:cond]) & @fields_mask[:cond]) != 0xf) and
|
@@ -57,7 +57,7 @@ class ARM
|
|
57
57
|
def decode_instr_op(edata, di)
|
58
58
|
op = di.opcode
|
59
59
|
di.instruction.opname = op.name
|
60
|
-
val = di.
|
60
|
+
val = di.misc # saved decoded u32
|
61
61
|
|
62
62
|
field_val = lambda { |f|
|
63
63
|
r = (val >> @fields_shift[f]) & @fields_mask[f]
|
@@ -267,6 +267,11 @@ class CCompiler < C::Compiler
|
|
267
267
|
e2 = inuse findreg(rsz)
|
268
268
|
op = ((type.specifier == :unsigned) ? 'movzx' : 'movsx')
|
269
269
|
op = 'mov' if e.sz == e2.sz
|
270
|
+
elsif e.sz > sz
|
271
|
+
e2 = inuse findreg(sz)
|
272
|
+
el, eh = get_composite_parts(e)
|
273
|
+
e = el
|
274
|
+
op = 'mov'
|
270
275
|
else
|
271
276
|
e2 = inuse findreg(sz)
|
272
277
|
op = 'mov'
|
@@ -779,6 +784,9 @@ class CCompiler < C::Compiler
|
|
779
784
|
else
|
780
785
|
instr 'mov', l, Reg.new(r.val, l.sz)
|
781
786
|
end
|
787
|
+
elsif r.kind_of? Composite
|
788
|
+
rl, rh = get_composite_parts r
|
789
|
+
instr 'mov', l, rl
|
782
790
|
else
|
783
791
|
instr 'mov', l, r
|
784
792
|
end
|
@@ -1329,11 +1337,11 @@ class CCompiler < C::Compiler
|
|
1329
1337
|
unuse l, r
|
1330
1338
|
if expr.lexpr.type.integral?
|
1331
1339
|
if expr.lexpr.type.name == :__int64 and @cpusz != 64
|
1332
|
-
raise # TODO
|
1340
|
+
raise "unsupported 64bit comparison #{expr}" # TODO
|
1333
1341
|
end
|
1334
1342
|
instr 'cmp', l, r
|
1335
1343
|
elsif expr.lexpr.type.float?
|
1336
|
-
raise # TODO
|
1344
|
+
raise "unsupported float comparison #{expr}" # TODO
|
1337
1345
|
instr 'fcmpp', l, r
|
1338
1346
|
else raise 'bad comparison ' + expr.to_s
|
1339
1347
|
end
|
@@ -1343,12 +1351,20 @@ class CCompiler < C::Compiler
|
|
1343
1351
|
r = c_cexpr_inner(expr.rexpr)
|
1344
1352
|
r = make_volatile(r, expr.rexpr.type)
|
1345
1353
|
unuse r
|
1354
|
+
if r.kind_of? Composite
|
1355
|
+
r, rh = get_composite_parts(r)
|
1356
|
+
instr 'or', r, rh
|
1357
|
+
end
|
1346
1358
|
instr 'test', r, r
|
1347
1359
|
instr 'jz', Expression[target]
|
1348
1360
|
else
|
1349
1361
|
r = c_cexpr_inner(expr)
|
1350
1362
|
r = make_volatile(r, expr.type)
|
1351
1363
|
unuse r
|
1364
|
+
if r.kind_of? Composite
|
1365
|
+
r, rh = get_composite_parts(r)
|
1366
|
+
instr 'or', r, rh
|
1367
|
+
end
|
1352
1368
|
instr 'test', r, r
|
1353
1369
|
instr 'jnz', Expression[target]
|
1354
1370
|
end
|
data/metasm/cpu/ia32/decode.rb
CHANGED
@@ -403,7 +403,12 @@ class Ia32
|
|
403
403
|
# ror a, b => (a >> b) | (a << (32-b))
|
404
404
|
{ a0 => Expression[[[[a0, :&, operandmask], e_op, sz], :|, [[a0, :&, operandmask], inv_op, isz]], :&, operandmask] }
|
405
405
|
}
|
406
|
-
when '
|
406
|
+
when 'shl', 'sal'; lambda { |di, a0, a1| { a0 => Expression[a0, (op[-1] == ?r ? :>> : :<<), [a1, :%, [opsz(di), 32].max]] } }
|
407
|
+
when 'sar'; lambda { |di, a0, a1|
|
408
|
+
sz = [opsz(di), 32].max
|
409
|
+
a1 = [a1, :%, sz]
|
410
|
+
{ a0 => Expression[[a0, :>>, a1], :|,
|
411
|
+
[[[mask[di], :*, sign[a0, di]], :<<, [sz, :-, a1]], :&, mask[di]]] } }
|
407
412
|
when 'shr'; lambda { |di, a0, a1| { a0 => Expression[[a0, :&, mask[di]], :>>, [a1, :%, opsz(di)]] } }
|
408
413
|
when 'shrd'
|
409
414
|
lambda { |di, a0, a1, a2|
|
@@ -423,7 +428,7 @@ class Ia32
|
|
423
428
|
when 'pop'
|
424
429
|
lambda { |di, a0| { esp => Expression[esp, :+, opsz(di)/8],
|
425
430
|
a0 => Indirection[esp, opsz(di)/8, di.address] } }
|
426
|
-
when 'pushfd', 'pushf'
|
431
|
+
when 'pushfd', 'pushf', 'pushfq'
|
427
432
|
# TODO Unknown per bit
|
428
433
|
lambda { |di|
|
429
434
|
efl = Expression[0x202]
|
@@ -434,7 +439,7 @@ class Ia32
|
|
434
439
|
bts[11, :eflag_o]
|
435
440
|
{ esp => Expression[esp, :-, opsz(di)/8], Indirection[esp, opsz(di)/8, di.address] => efl }
|
436
441
|
}
|
437
|
-
when 'popfd', 'popf'
|
442
|
+
when 'popfd', 'popf', 'popfq'
|
438
443
|
lambda { |di| bt = lambda { |pos| Expression[[Indirection[esp, opsz(di)/8, di.address], :>>, pos], :&, 1] }
|
439
444
|
{ esp => Expression[esp, :+, opsz(di)/8], :eflag_c => bt[0], :eflag_z => bt[6], :eflag_s => bt[7], :eflag_o => bt[11] } }
|
440
445
|
when 'sahf'
|
@@ -551,7 +556,7 @@ class Ia32
|
|
551
556
|
op =~ /^(stos|movs|lods|scas|cmps)([bwdq])$/
|
552
557
|
e_op = $1
|
553
558
|
sz = { 'b' => 1, 'w' => 2, 'd' => 4, 'q' => 8 }[$2]
|
554
|
-
eax_ = Reg.new(0, 8*sz).symbolic
|
559
|
+
eax_ = self.class::Reg.new(0, 8*sz).symbolic
|
555
560
|
dir = :+
|
556
561
|
if di.block and (di.block.list.find { |ddi| ddi.opcode.name == 'std' } rescue nil)
|
557
562
|
dir = :-
|
@@ -11,10 +11,19 @@ class Ia32
|
|
11
11
|
# temporarily setup dasm.address_binding so that backtracking
|
12
12
|
# stack-related offsets resolve in :frameptr (relative to func start)
|
13
13
|
def decompile_makestackvars(dasm, funcstart, blocks)
|
14
|
+
esp = register_symbols[4]
|
14
15
|
oldfuncbd = dasm.address_binding[funcstart]
|
15
|
-
dasm.address_binding[funcstart] = {
|
16
|
-
|
16
|
+
dasm.address_binding[funcstart] = { esp => :frameptr }
|
17
17
|
patched_binding = [funcstart] # list of addresses to cleanup later
|
18
|
+
|
19
|
+
if blocks.length <= 12
|
20
|
+
blocks.each { |block| yield block }
|
21
|
+
return
|
22
|
+
end
|
23
|
+
|
24
|
+
# for large function, pre-trace and cache esp/ebp for every block start to improve decompilation time
|
25
|
+
|
26
|
+
ebp = register_symbols[5]
|
18
27
|
ebp_frame = true
|
19
28
|
|
20
29
|
# pretrace esp and ebp for each function block (cleared later)
|
@@ -24,16 +33,16 @@ class Ia32
|
|
24
33
|
if not dasm.address_binding[blockstart]
|
25
34
|
patched_binding << blockstart
|
26
35
|
dasm.address_binding[blockstart] = {}
|
27
|
-
foo = dasm.backtrace(
|
36
|
+
foo = dasm.backtrace(esp, blockstart, :snapshot_addr => funcstart)
|
28
37
|
if foo.length == 1 and ee = foo.first and ee.kind_of? Expression and (ee == Expression[:frameptr] or
|
29
38
|
(ee.lexpr == :frameptr and ee.op == :+ and ee.rexpr.kind_of? ::Integer))
|
30
|
-
dasm.address_binding[blockstart][
|
39
|
+
dasm.address_binding[blockstart][esp] = ee
|
31
40
|
end
|
32
41
|
if ebp_frame
|
33
|
-
foo = dasm.backtrace(
|
42
|
+
foo = dasm.backtrace(ebp, blockstart, :snapshot_addr => funcstart)
|
34
43
|
if foo.length == 1 and ee = foo.first and ee.kind_of? Expression and (ee == Expression[:frameptr] or
|
35
44
|
(ee.lexpr == :frameptr and ee.op == :+ and ee.rexpr.kind_of? ::Integer))
|
36
|
-
dasm.address_binding[blockstart][
|
45
|
+
dasm.address_binding[blockstart][ebp] = ee
|
37
46
|
else
|
38
47
|
ebp_frame = false # func does not use ebp as frame ptr, no need to bt for later blocks
|
39
48
|
end
|
@@ -48,6 +57,11 @@ class Ia32
|
|
48
57
|
dasm.address_binding[funcstart] = oldfuncbd if oldfuncbd
|
49
58
|
end
|
50
59
|
|
60
|
+
# add di-specific registry written/accessed
|
61
|
+
def decompile_func_finddeps_di(dcmp, func, di, a, w)
|
62
|
+
a << :eax if di.opcode.name == 'ret' and (not func.type.kind_of? C::BaseType or func.type.type.name != :void) # standard ABI
|
63
|
+
end
|
64
|
+
|
51
65
|
# list variable dependency for each block, remove useless writes
|
52
66
|
# returns { blockaddr => [list of vars that are needed by a following block] }
|
53
67
|
def decompile_func_finddeps(dcmp, blocks, func)
|
@@ -69,7 +83,7 @@ class Ia32
|
|
69
83
|
else a |= Expression[k].externals # if dword [eax] <- 42, eax is read
|
70
84
|
end
|
71
85
|
}
|
72
|
-
|
86
|
+
decompile_func_finddeps_di(dcmp, func, di, a, w)
|
73
87
|
|
74
88
|
deps_r[b] |= a.map { |ee| Expression[ee].externals.grep(::Symbol) }.flatten - [:unknown] - deps_w[b]
|
75
89
|
deps_w[b] |= w.map { |ee| Expression[ee].externals.grep(::Symbol) }.flatten - [:unknown]
|
@@ -120,7 +134,7 @@ class Ia32
|
|
120
134
|
else a |= Expression[k].externals # if dword [eax] <- 42, eax is read
|
121
135
|
end
|
122
136
|
}
|
123
|
-
|
137
|
+
decompile_func_finddeps_di(dcmp, func, di, a, w)
|
124
138
|
|
125
139
|
next true if (a.map { |ee| Expression[ee].externals.grep(::Symbol) }.flatten - [:unknown] - bw).include? r
|
126
140
|
bw |= w.map { |ee| Expression[ee].externals.grep(::Symbol) }.flatten - [:unknown]
|
data/metasm/cpu/ia32/opcodes.rb
CHANGED
@@ -475,7 +475,7 @@ class Ia32
|
|
475
475
|
addop 'pavgb', [0x0F, 0xE0], :mrmmmx
|
476
476
|
addop 'pavgw', [0x0F, 0xE3], :mrmmmx
|
477
477
|
addop 'pextrw', [0x0F, 0xC5, 0xC0], nil, {:reg => [2, 3], :regmmx => [2, 0]}, :reg, :regmmx, :u8
|
478
|
-
addop 'pinsrw', [0x0F, 0xC4, 0x00], nil, {:modrm => [2, 0], :regmmx => [2, 3]}, :
|
478
|
+
addop 'pinsrw', [0x0F, 0xC4, 0x00], nil, {:modrm => [2, 0], :regmmx => [2, 3]}, :regmmx, :modrm, :u8
|
479
479
|
addop 'pmaxsw', [0x0F, 0xEE], :mrmmmx
|
480
480
|
addop 'pmaxub', [0x0F, 0xDE], :mrmmmx
|
481
481
|
addop 'pminsw', [0x0F, 0xEA], :mrmmmx
|
@@ -644,7 +644,7 @@ class Ia32
|
|
644
644
|
addop('vmclear', [0x0F, 0xC7, 6<<3], :modrmA) { |o| o.props[:argsz] = 64 ; o.props[:needpfx] = 0x66 }
|
645
645
|
addop('vmxon', [0x0F, 0xC7, 6<<3], :modrmA) { |o| o.props[:argsz] = 64 ; o.props[:needpfx] = 0xF3 }
|
646
646
|
addop('vmptrld', [0x0F, 0xC7, 6<<3], :modrmA) { |o| o.props[:argsz] = 64 }
|
647
|
-
addop('
|
647
|
+
addop('vmptrst', [0x0F, 0xC7, 7<<3], :modrmA) { |o| o.props[:argsz] = 64 }
|
648
648
|
addop('invept', [0x0F, 0x38, 0x80], :mrmA) { |o| o.props[:needpfx] = 0x66 }
|
649
649
|
addop('invvpid', [0x0F, 0x38, 0x81], :mrmA) { |o| o.props[:needpfx] = 0x66 }
|
650
650
|
|
@@ -674,9 +674,9 @@ class Ia32
|
|
674
674
|
addop('pblendvb', [0x0F, 0x38, 0x10], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
675
675
|
addop('pblendw', [0x0F, 0x3A, 0x1E], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66 }
|
676
676
|
addop('pcmpeqq', [0x0F, 0x38, 0x29], :mrmxmm) { |o| o.props[:needpfx] = 0x66 }
|
677
|
-
addop('pextrb', [0x0F, 0x3A, 0x14], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args
|
678
|
-
addop('pextrw', [0x0F, 0x3A, 0x15], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args
|
679
|
-
addop('pextrd', [0x0F, 0x3A, 0x16], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args
|
677
|
+
addop('pextrb', [0x0F, 0x3A, 0x14], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args.index(:modrmxmm); o.args.unshift(:modrm); o.props[:argsz] = 8 }
|
678
|
+
addop('pextrw', [0x0F, 0x3A, 0x15], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args.index(:modrmxmm); o.args.unshift(:modrm); o.props[:argsz] = 16 }
|
679
|
+
addop('pextrd', [0x0F, 0x3A, 0x16], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args.index(:modrmxmm); o.args.unshift(:modrm); o.props[:argsz] = 32 }
|
680
680
|
addop('pinsrb', [0x0F, 0x3A, 0x20], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 8 }
|
681
681
|
addop('pinsrw', [0x0F, 0x3A, 0x21], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 16 }
|
682
682
|
addop('pinsrd', [0x0F, 0x3A, 0x22], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 32 }
|
data/metasm/cpu/mcs51.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
2
|
+
# Copyright (C) 2015-2016 Google
|
3
|
+
#
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
5
|
+
|
6
|
+
|
7
|
+
require 'metasm/cpu/mcs51/opcodes'
|
8
|
+
require 'metasm/decode'
|
9
|
+
|
10
|
+
module Metasm
|
11
|
+
class MCS51
|
12
|
+
|
13
|
+
def build_opcode_bin_mask(op)
|
14
|
+
op.bin_mask = 0
|
15
|
+
op.fields.each { |f, off|
|
16
|
+
op.bin_mask |= (@fields_mask[f] << off)
|
17
|
+
}
|
18
|
+
op.bin_mask ^= 0xff
|
19
|
+
end
|
20
|
+
|
21
|
+
def build_bin_lookaside
|
22
|
+
lookaside = Array.new(256) { [] }
|
23
|
+
opcode_list.each { |op|
|
24
|
+
build_opcode_bin_mask op
|
25
|
+
b = op.bin
|
26
|
+
msk = op.bin_mask
|
27
|
+
for i in b..(b | (255^msk))
|
28
|
+
lookaside[i] << op if i & msk == b & msk
|
29
|
+
end
|
30
|
+
}
|
31
|
+
lookaside
|
32
|
+
end
|
33
|
+
|
34
|
+
def decode_findopcode(edata)
|
35
|
+
di = DecodedInstruction.new self
|
36
|
+
byte = edata.data[edata.ptr]
|
37
|
+
byte = byte.unpack('C').first if byte.kind_of?(::String)
|
38
|
+
if not byte
|
39
|
+
return
|
40
|
+
end
|
41
|
+
return di if di.opcode = @bin_lookaside[byte].find { |op|
|
42
|
+
byte & op.bin_mask == op.bin & op.bin_mask
|
43
|
+
}
|
44
|
+
end
|
45
|
+
|
46
|
+
def decode_instr_op(edata, di)
|
47
|
+
before_ptr = edata.ptr
|
48
|
+
op = di.opcode
|
49
|
+
di.instruction.opname = op.name
|
50
|
+
bseq = edata.get_byte
|
51
|
+
|
52
|
+
field_val = lambda { |f|
|
53
|
+
if fld = op.fields[f]
|
54
|
+
(bseq >> fld) & @fields_mask[f]
|
55
|
+
end
|
56
|
+
}
|
57
|
+
|
58
|
+
op.args.each { |a|
|
59
|
+
di.instruction.args << case a
|
60
|
+
when :rel8
|
61
|
+
Expression[edata.decode_imm(:i8, @endianness)]
|
62
|
+
when :d8
|
63
|
+
Immediate.new(edata.decode_imm(:u8, @endianness))
|
64
|
+
when :m8
|
65
|
+
Memref.new(nil, edata.decode_imm(:u8, @endianness))
|
66
|
+
when :rd
|
67
|
+
if (field_val[a] & 0b1110) == 0b0110
|
68
|
+
Memref.new(Reg.new(field_val[a] + 2), nil)
|
69
|
+
else
|
70
|
+
Reg.new(field_val[a])
|
71
|
+
end
|
72
|
+
when :r_a
|
73
|
+
Reg.from_str('A')
|
74
|
+
when :r_b
|
75
|
+
Reg.from_str('B')
|
76
|
+
when :r_c
|
77
|
+
Reg.from_str('C')
|
78
|
+
when :addr_11
|
79
|
+
Memref.new(nil, edata.decode_imm(:u8, @endianness))
|
80
|
+
when :addr_16
|
81
|
+
Memref.new(nil, edata.decode_imm(:u16, @endianness))
|
82
|
+
end
|
83
|
+
}
|
84
|
+
|
85
|
+
di.bin_length += edata.ptr - before_ptr
|
86
|
+
|
87
|
+
di
|
88
|
+
end
|
89
|
+
|
90
|
+
def backtrace_binding(b)
|
91
|
+
@backtrace_binding ||= {}
|
92
|
+
end
|
93
|
+
|
94
|
+
def get_xrefs_x(b,c)
|
95
|
+
[]
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
2
|
+
# Copyright (C) 2015-2016 Google
|
3
|
+
#
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
5
|
+
|
6
|
+
|
7
|
+
require 'metasm/main'
|
8
|
+
|
9
|
+
module Metasm
|
10
|
+
class MCS51 < CPU
|
11
|
+
|
12
|
+
class Reg
|
13
|
+
I_TO_S = { 0x4 => 'A',
|
14
|
+
0x5 => 'B',
|
15
|
+
0x8 => 'R0',
|
16
|
+
0x9 => 'R1',
|
17
|
+
0xA => 'R2',
|
18
|
+
0xB => 'R3',
|
19
|
+
0xC => 'R4',
|
20
|
+
0xD => 'R5',
|
21
|
+
0xE => 'R6',
|
22
|
+
0xF => 'R7'
|
23
|
+
}
|
24
|
+
|
25
|
+
S_TO_I = { 'A' => 0x4,
|
26
|
+
'B' => 0x5 }
|
27
|
+
|
28
|
+
def initialize(i)
|
29
|
+
@i = i
|
30
|
+
end
|
31
|
+
|
32
|
+
def to_s
|
33
|
+
I_TO_S[@i]
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.from_str(s)
|
37
|
+
new(S_TO_I[s])
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
class Immediate
|
43
|
+
def initialize(value)
|
44
|
+
@value = value
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_s
|
48
|
+
"#" + @value.to_s
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class Memref
|
53
|
+
attr_accessor :base, :offset
|
54
|
+
def initialize(base, offset)
|
55
|
+
@base = base
|
56
|
+
@offset = offset
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_s
|
60
|
+
@base ? "@" + @base.to_s : @offset.to_s
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def initialize
|
65
|
+
super()
|
66
|
+
@endianness = :big
|
67
|
+
@size = 8
|
68
|
+
end
|
69
|
+
|
70
|
+
def init_opcode_list
|
71
|
+
init_mcs51
|
72
|
+
@opcode_list
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|