metasm 1.0.2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/Gemfile +1 -0
  4. data/doc/code_organisation.txt +1 -1
  5. data/metasm.gemspec +1 -1
  6. data/metasm.rb +2 -1
  7. data/metasm/cpu/arc/decode.rb +3 -3
  8. data/metasm/cpu/arm/decode.rb +2 -2
  9. data/metasm/cpu/ia32/compile_c.rb +18 -2
  10. data/metasm/cpu/ia32/decode.rb +9 -4
  11. data/metasm/cpu/ia32/decompile.rb +22 -8
  12. data/metasm/cpu/ia32/opcodes.rb +5 -5
  13. data/metasm/cpu/mcs51.rb +8 -0
  14. data/metasm/cpu/mcs51/decode.rb +99 -0
  15. data/metasm/cpu/mcs51/main.rb +76 -0
  16. data/metasm/cpu/mcs51/opcodes.rb +120 -0
  17. data/metasm/cpu/mips/decode.rb +5 -4
  18. data/metasm/cpu/st20.rb +9 -0
  19. data/metasm/cpu/st20/decode.rb +180 -0
  20. data/metasm/cpu/st20/decompile.rb +283 -0
  21. data/metasm/cpu/st20/main.rb +37 -0
  22. data/metasm/cpu/st20/opcodes.rb +140 -0
  23. data/metasm/cpu/x86_64/encode.rb +4 -2
  24. data/metasm/cpu/x86_64/opcodes.rb +4 -2
  25. data/metasm/decode.rb +16 -15
  26. data/metasm/decompile.rb +1 -1
  27. data/metasm/disassemble.rb +3 -1
  28. data/metasm/disassemble_api.rb +3 -1
  29. data/metasm/dynldr.rb +9 -3
  30. data/metasm/encode.rb +2 -2
  31. data/metasm/exe_format/coff.rb +3 -1
  32. data/metasm/exe_format/coff_decode.rb +5 -3
  33. data/metasm/exe_format/elf.rb +4 -0
  34. data/metasm/exe_format/elf_decode.rb +1 -2
  35. data/metasm/exe_format/elf_encode.rb +4 -1
  36. data/metasm/exe_format/macho.rb +20 -6
  37. data/metasm/exe_format/pe.rb +1 -1
  38. data/metasm/exe_format/serialstruct.rb +1 -1
  39. data/metasm/gui.rb +1 -1
  40. data/metasm/gui/dasm_hex.rb +2 -2
  41. data/metasm/gui/dasm_main.rb +8 -8
  42. data/metasm/gui/debug.rb +4 -4
  43. data/metasm/gui/gtk.rb +1 -1
  44. data/metasm/gui/qt.rb +2 -2
  45. data/metasm/gui/win32.rb +1 -1
  46. data/metasm/main.rb +11 -6
  47. data/metasm/os/windows.rb +26 -23
  48. data/misc/hexdump.rb +2 -2
  49. data/misc/objdiff.rb +4 -1
  50. data/misc/objscan.rb +1 -1
  51. data/samples/dasm-plugins/bindiff.rb +1 -1
  52. data/samples/dasm-plugins/scanxrefs.rb +2 -1
  53. data/samples/dynamic_ruby.rb +24 -25
  54. data/samples/elfencode.rb +15 -0
  55. data/samples/exeencode.rb +2 -2
  56. data/samples/metasm-shell.rb +67 -55
  57. data/tests/mcs51.rb +27 -0
  58. metadata +13 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 67b43e2e4f4fb324ee2ea574e15cb2eec4ed1215
4
- data.tar.gz: 4b9dcff449fe4ec812e03c52ab8cc2611f05ad46
3
+ metadata.gz: 8a5dcb50d2a38105adee7c8249698e2f675af544
4
+ data.tar.gz: 0476236904d2bc2b8d45013446a58d053f0f24aa
5
5
  SHA512:
6
- metadata.gz: 1b14f7f6c2f68761a258ecb40e4b59f29f968a128d2560c59cf40a81cb30a8a9e1f16c4b89a6ccf674fdd203083c443d883dbfbdec54a687f6db9af2817a1954
7
- data.tar.gz: 2724ae05df0770e22d1c11d8d00b15ca911df0d89d21b12858d219ce9974d45b1fe4b34b3f1d5d8614a4fda699d424a7c11c3c02ee21435803f03b079c7d7d24
6
+ metadata.gz: ad41d74f97fab2567509acddb90ea7124c317519e84af509c6e68d07839ff1015a2c4512286e76eb16db22efa481aa60531beeb66e5ec9c0677727ba6cf81571
7
+ data.tar.gz: 333a45fd258674ead5f2b036e56e8e87ad06b4aa74b5f655495d05b902394527dad0abf78e614c7d6f715caa3d92c05b322166bfed74fb611ad3ddabbd4f7a1c
data/.gitignore CHANGED
@@ -1 +1,3 @@
1
1
  pkg/**
2
+ doc/**/*.html
3
+ metasm/dynldr-*.so
data/Gemfile CHANGED
@@ -1 +1,2 @@
1
+ source 'https://rubygems.org'
1
2
  gemspec
@@ -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 chose among the available GUI backend
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
 
@@ -4,7 +4,7 @@ require 'metasm'
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = 'metasm'
7
- s.version = '1.0.2'
7
+ s.version = '1.0.3'
8
8
  s.summary =
9
9
  "Metasm is a cross-architecture assembler, disassembler, linker, and debugger."
10
10
  s.description = ""
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',
@@ -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 $ARC_DEBUG and (val & opcode.bin_mask) == opcode.bin
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]
@@ -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.instance_variable_set('@raw', val)
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.instance_variable_get('@raw')
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
@@ -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 'sar', 'shl', 'sal'; lambda { |di, a0, a1| { a0 => Expression[a0, (op[-1] == ?r ? :>> : :<<), [a1, :%, [opsz(di), 32].max]] } }
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] = { :esp => :frameptr } # this would suffice, the rest here is just optimisation
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(:esp, blockstart, :snapshot_addr => funcstart)
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][:esp] = ee
39
+ dasm.address_binding[blockstart][esp] = ee
31
40
  end
32
41
  if ebp_frame
33
- foo = dasm.backtrace(:ebp, blockstart, :snapshot_addr => funcstart)
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][:ebp] = ee
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
- a << :eax if di.opcode.name == 'ret' and (not func.type.kind_of? C::BaseType or func.type.type.name != :void) # standard ABI
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
- a << :eax if di.opcode.name == 'ret' and (not func.type.kind_of? C::BaseType or func.type.type.name != :void) # standard ABI
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]
@@ -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]}, :modrm, :regmmx, :u8
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('vmptrrst', [0x0F, 0xC7, 7<<3], :modrmA) { |o| o.props[:argsz] = 64 }
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[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 8 }
678
- addop('pextrw', [0x0F, 0x3A, 0x15], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 16 }
679
- addop('pextrd', [0x0F, 0x3A, 0x16], :mrmxmm, :u8) { |o| o.props[:needpfx] = 0x66; o.args[o.args.index(:modrmxmm)] = :modrm; o.props[:argsz] = 32 }
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 }
@@ -0,0 +1,8 @@
1
+ # This file is part of Metasm, the Ruby assembly manipulation suite
2
+ # Copyright (C) 2015 Google
3
+ #
4
+ # Licence is LGPL, see LICENCE in the top-level directory
5
+
6
+
7
+ require 'metasm/main'
8
+ require 'metasm/cpu/mcs51/decode'
@@ -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
+