metasm 1.0.2 → 1.0.3
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 +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
|
+
|