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.
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
+