metasm 1.0.1 → 1.0.2

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 (235) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.hgtags +3 -0
  4. data/Gemfile +1 -0
  5. data/INSTALL +61 -0
  6. data/LICENCE +458 -0
  7. data/README +29 -21
  8. data/Rakefile +10 -0
  9. data/TODO +10 -12
  10. data/doc/code_organisation.txt +2 -0
  11. data/doc/core/DynLdr.txt +247 -0
  12. data/doc/core/ExeFormat.txt +43 -0
  13. data/doc/core/Expression.txt +220 -0
  14. data/doc/core/GNUExports.txt +27 -0
  15. data/doc/core/Ia32.txt +236 -0
  16. data/doc/core/SerialStruct.txt +108 -0
  17. data/doc/core/VirtualString.txt +145 -0
  18. data/doc/core/WindowsExports.txt +61 -0
  19. data/doc/core/index.txt +1 -0
  20. data/doc/style.css +6 -3
  21. data/doc/usage/debugger.txt +327 -0
  22. data/doc/usage/index.txt +1 -0
  23. data/doc/use_cases.txt +2 -2
  24. data/metasm.gemspec +22 -0
  25. data/{lib/metasm.rb → metasm.rb} +11 -3
  26. data/{lib/metasm → metasm}/compile_c.rb +13 -7
  27. data/metasm/cpu/arc.rb +8 -0
  28. data/metasm/cpu/arc/decode.rb +425 -0
  29. data/metasm/cpu/arc/main.rb +191 -0
  30. data/metasm/cpu/arc/opcodes.rb +588 -0
  31. data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
  32. data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
  33. data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
  34. data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
  35. data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
  36. data/metasm/cpu/arm/opcodes.rb +324 -0
  37. data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
  38. data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
  39. data/metasm/cpu/arm64.rb +15 -0
  40. data/metasm/cpu/arm64/debug.rb +38 -0
  41. data/metasm/cpu/arm64/decode.rb +289 -0
  42. data/metasm/cpu/arm64/encode.rb +41 -0
  43. data/metasm/cpu/arm64/main.rb +105 -0
  44. data/metasm/cpu/arm64/opcodes.rb +232 -0
  45. data/metasm/cpu/arm64/parse.rb +20 -0
  46. data/metasm/cpu/arm64/render.rb +95 -0
  47. data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
  48. data/metasm/cpu/bpf/decode.rb +142 -0
  49. data/metasm/cpu/bpf/main.rb +60 -0
  50. data/metasm/cpu/bpf/opcodes.rb +81 -0
  51. data/metasm/cpu/bpf/render.rb +41 -0
  52. data/metasm/cpu/cy16.rb +9 -0
  53. data/metasm/cpu/cy16/decode.rb +253 -0
  54. data/metasm/cpu/cy16/main.rb +63 -0
  55. data/metasm/cpu/cy16/opcodes.rb +78 -0
  56. data/metasm/cpu/cy16/render.rb +41 -0
  57. data/metasm/cpu/dalvik.rb +11 -0
  58. data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
  59. data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
  60. data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
  61. data/metasm/cpu/ia32.rb +17 -0
  62. data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
  63. data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
  64. data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
  65. data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
  66. data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
  67. data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
  68. data/metasm/cpu/ia32/opcodes.rb +1424 -0
  69. data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
  70. data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
  71. data/metasm/cpu/mips.rb +14 -0
  72. data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
  73. data/metasm/cpu/mips/debug.rb +42 -0
  74. data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
  75. data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
  76. data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
  77. data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
  78. data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
  79. data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
  80. data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
  81. data/metasm/cpu/msp430/decode.rb +247 -0
  82. data/metasm/cpu/msp430/main.rb +62 -0
  83. data/metasm/cpu/msp430/opcodes.rb +101 -0
  84. data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
  85. data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
  86. data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
  87. data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
  88. data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
  89. data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
  90. data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
  91. data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
  92. data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
  93. data/metasm/cpu/ppc/parse.rb +55 -0
  94. data/metasm/cpu/python.rb +8 -0
  95. data/metasm/cpu/python/decode.rb +136 -0
  96. data/metasm/cpu/python/main.rb +36 -0
  97. data/metasm/cpu/python/opcodes.rb +180 -0
  98. data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
  99. data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
  100. data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
  101. data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
  102. data/metasm/cpu/x86_64.rb +15 -0
  103. data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
  104. data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
  105. data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
  106. data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
  107. data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
  108. data/metasm/cpu/x86_64/opcodes.rb +136 -0
  109. data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
  110. data/metasm/cpu/x86_64/render.rb +35 -0
  111. data/metasm/cpu/z80.rb +9 -0
  112. data/metasm/cpu/z80/decode.rb +313 -0
  113. data/metasm/cpu/z80/main.rb +67 -0
  114. data/metasm/cpu/z80/opcodes.rb +224 -0
  115. data/metasm/cpu/z80/render.rb +59 -0
  116. data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
  117. data/{lib/metasm → metasm}/decode.rb +35 -4
  118. data/{lib/metasm → metasm}/decompile.rb +15 -16
  119. data/{lib/metasm → metasm}/disassemble.rb +201 -45
  120. data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
  121. data/{lib/metasm → metasm}/dynldr.rb +220 -133
  122. data/{lib/metasm → metasm}/encode.rb +10 -1
  123. data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
  124. data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
  125. data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
  126. data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
  127. data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
  128. data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
  129. data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
  130. data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
  131. data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
  132. data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
  133. data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
  134. data/metasm/exe_format/gb.rb +65 -0
  135. data/metasm/exe_format/javaclass.rb +424 -0
  136. data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
  137. data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
  138. data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
  139. data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
  140. data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
  141. data/metasm/exe_format/pyc.rb +167 -0
  142. data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
  143. data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
  144. data/metasm/exe_format/shellcode_rwx.rb +114 -0
  145. data/metasm/exe_format/swf.rb +205 -0
  146. data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
  147. data/metasm/exe_format/zip.rb +335 -0
  148. data/metasm/gui.rb +13 -0
  149. data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
  150. data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
  151. data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
  152. data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
  153. data/metasm/gui/dasm_graph.rb +1695 -0
  154. data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
  155. data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
  156. data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
  157. data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
  158. data/{lib/metasm → metasm}/gui/debug.rb +93 -27
  159. data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
  160. data/{lib/metasm → metasm}/gui/qt.rb +12 -2
  161. data/{lib/metasm → metasm}/gui/win32.rb +179 -42
  162. data/{lib/metasm → metasm}/gui/x11.rb +59 -59
  163. data/{lib/metasm → metasm}/main.rb +389 -264
  164. data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
  165. data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
  166. data/{lib/metasm → metasm}/os/linux.rb +628 -151
  167. data/metasm/os/main.rb +330 -0
  168. data/{lib/metasm → metasm}/os/windows.rb +132 -42
  169. data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
  170. data/{lib/metasm → metasm}/parse.rb +26 -24
  171. data/{lib/metasm → metasm}/parse_c.rb +221 -116
  172. data/{lib/metasm → metasm}/preprocessor.rb +55 -40
  173. data/{lib/metasm → metasm}/render.rb +14 -38
  174. data/misc/hexdump.rb +2 -1
  175. data/misc/lint.rb +58 -0
  176. data/misc/txt2html.rb +9 -7
  177. data/samples/bindiff.rb +3 -4
  178. data/samples/dasm-plugins/bindiff.rb +15 -0
  179. data/samples/dasm-plugins/bookmark.rb +133 -0
  180. data/samples/dasm-plugins/c_constants.rb +57 -0
  181. data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
  182. data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
  183. data/samples/dasm-plugins/dasm_all.rb +70 -0
  184. data/samples/dasm-plugins/demangle_cpp.rb +31 -0
  185. data/samples/dasm-plugins/deobfuscate.rb +251 -0
  186. data/samples/dasm-plugins/dump_text.rb +35 -0
  187. data/samples/dasm-plugins/export_graph_svg.rb +86 -0
  188. data/samples/dasm-plugins/findgadget.rb +75 -0
  189. data/samples/dasm-plugins/hl_opcode.rb +32 -0
  190. data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
  191. data/samples/dasm-plugins/imm2off.rb +34 -0
  192. data/samples/dasm-plugins/match_libsigs.rb +93 -0
  193. data/samples/dasm-plugins/patch_file.rb +95 -0
  194. data/samples/dasm-plugins/scanfuncstart.rb +36 -0
  195. data/samples/dasm-plugins/scanxrefs.rb +26 -0
  196. data/samples/dasm-plugins/selfmodify.rb +197 -0
  197. data/samples/dasm-plugins/stringsxrefs.rb +28 -0
  198. data/samples/dasmnavig.rb +1 -1
  199. data/samples/dbg-apihook.rb +24 -9
  200. data/samples/dbg-plugins/heapscan.rb +283 -0
  201. data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
  202. data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
  203. data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
  204. data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
  205. data/samples/dbg-plugins/heapscan/winheap.h +174 -0
  206. data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
  207. data/samples/dbg-plugins/trace_func.rb +214 -0
  208. data/samples/disassemble-gui.rb +35 -5
  209. data/samples/disassemble.rb +31 -6
  210. data/samples/dump_upx.rb +24 -12
  211. data/samples/dynamic_ruby.rb +12 -3
  212. data/samples/exeencode.rb +6 -5
  213. data/samples/factorize-headers-peimports.rb +1 -1
  214. data/samples/lindebug.rb +175 -381
  215. data/samples/metasm-shell.rb +1 -2
  216. data/samples/peldr.rb +2 -2
  217. data/tests/all.rb +1 -1
  218. data/tests/arc.rb +26 -0
  219. data/tests/dynldr.rb +22 -4
  220. data/tests/expression.rb +55 -0
  221. data/tests/graph_layout.rb +285 -0
  222. data/tests/ia32.rb +79 -26
  223. data/tests/mips.rb +9 -2
  224. data/tests/x86_64.rb +66 -18
  225. metadata +330 -218
  226. data/lib/metasm/arm/opcodes.rb +0 -177
  227. data/lib/metasm/gui.rb +0 -23
  228. data/lib/metasm/gui/dasm_graph.rb +0 -1354
  229. data/lib/metasm/ia32.rb +0 -14
  230. data/lib/metasm/ia32/opcodes.rb +0 -873
  231. data/lib/metasm/ppc/parse.rb +0 -52
  232. data/lib/metasm/x86_64.rb +0 -12
  233. data/lib/metasm/x86_64/opcodes.rb +0 -118
  234. data/samples/gdbclient.rb +0 -583
  235. data/samples/rubstop.rb +0 -399
@@ -0,0 +1,15 @@
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
+ class Metasm::X86_64 < Metasm::Ia32
7
+ end
8
+
9
+ require 'metasm/main'
10
+ require 'metasm/cpu/x86_64/parse'
11
+ require 'metasm/cpu/x86_64/encode'
12
+ require 'metasm/cpu/x86_64/decode'
13
+ require 'metasm/cpu/x86_64/render'
14
+ require 'metasm/cpu/x86_64/debug'
15
+ require 'metasm/cpu/x86_64/compile_c'
@@ -4,7 +4,7 @@
4
4
  # Licence is LGPL, see LICENCE in the top-level directory
5
5
 
6
6
 
7
- require 'metasm/x86_64/parse'
7
+ require 'metasm/cpu/x86_64/parse'
8
8
  require 'metasm/compile_c'
9
9
 
10
10
  module Metasm
@@ -236,7 +236,7 @@ class CCompiler < C::Compiler
236
236
  e2
237
237
  elsif type.float?
238
238
  raise 'float unhandled'
239
- else raise
239
+ else raise "cannot cast #{e} to #{type}"
240
240
  end
241
241
  elsif e.kind_of? Address
242
242
  make_volatile resolve_address(e), type, rsz
@@ -247,6 +247,7 @@ class CCompiler < C::Compiler
247
247
  e2
248
248
  elsif type.float?
249
249
  raise 'float unhandled'
250
+ else raise "cannot cast #{e} to #{type}"
250
251
  end
251
252
  else
252
253
  e
@@ -262,7 +263,7 @@ class CCompiler < C::Compiler
262
263
  elsif i >= (1<<64)-0x8000_0000
263
264
  v = Expression[Expression.make_signed(i, 64)]
264
265
  else
265
- v = make_volatile(v)
266
+ v = make_volatile(v, C::BaseType.new(:int))
266
267
  unuse v
267
268
  end
268
269
  end
@@ -417,7 +418,6 @@ class CCompiler < C::Compiler
417
418
  r = reg
418
419
  end
419
420
  end
420
- else raise
421
421
  end
422
422
  r
423
423
  end
@@ -512,6 +512,7 @@ class CCompiler < C::Compiler
512
512
  end
513
513
  when :-
514
514
  r = c_cexpr_inner(expr.rexpr)
515
+ r = resolve_address r if r.kind_of? Address
515
516
  if r.kind_of? Expression
516
517
  unuse l, r
517
518
  l = Address.new(l.modrm.dup)
@@ -574,6 +575,13 @@ class CCompiler < C::Compiler
574
575
  else
575
576
  instr 'mov', l, Reg.new(r.val, l.sz)
576
577
  end
578
+ elsif l.kind_of? ModRM and r.kind_of? Expression and l.sz == 64
579
+ rval = r.reduce
580
+ if !rval.kind_of?(Integer) or rval > 0xffff_ffff or rval < -0x8000_0000
581
+ r = make_volatile(r, expr.type)
582
+ unuse r
583
+ end
584
+ instr 'mov', l, r
577
585
  else
578
586
  instr 'mov', l, r
579
587
  end
@@ -586,6 +594,7 @@ class CCompiler < C::Compiler
586
594
  l = c_cexpr_inner(expr.lexpr)
587
595
  l = make_volatile(l, expr.type)
588
596
  r = c_cexpr_inner(expr.rexpr)
597
+ r = make_volatile(r, expr.type) if r.kind_of?(ModRM) and r.sz != l.sz
589
598
  unuse r
590
599
  if expr.lexpr.type.integral? or expr.lexpr.type.pointer?
591
600
  instr 'cmp', l, i_to_i32(r)
@@ -611,7 +620,6 @@ class CCompiler < C::Compiler
611
620
  ft = ft.pointed if ft.pointer?
612
621
  ft = nil if not ft.kind_of? C::Function
613
622
 
614
- arglist = expr.rexpr.dup
615
623
  regargsmask = @state.regargs.dup
616
624
  if ft
617
625
  ft.args.each_with_index { |a, i|
@@ -639,8 +647,8 @@ class CCompiler < C::Compiler
639
647
  stackargs = expr.rexpr.zip(regargsmask).map { |a, r| a if not r }.compact
640
648
 
641
649
  # preserve 16byte stack align under windows
642
- stackalign = true if (stackargs + backup).length & 1 == 1
643
- instr 'push', rax if stackalign
650
+ stackalign = true if @state.args_space > 0 and (stackargs + backup).length & 1 == 1
651
+ instr 'sub', Reg.new(4, @cpusz), Expression[8] if stackalign
644
652
 
645
653
  stackargs.reverse_each { |arg|
646
654
  raise 'arg unhandled' if not arg.type.integral? or arg.type.pointer?
@@ -652,7 +660,7 @@ class CCompiler < C::Compiler
652
660
  }
653
661
 
654
662
  regargs_unuse = []
655
- regargsmask.zip(expr.rexpr).each { |ra, arg|
663
+ regargsmask.zip(expr.rexpr).reverse_each { |ra, arg|
656
664
  next if not arg or not ra
657
665
  a = c_cexpr_inner(arg)
658
666
  a = resolve_address a if a.kind_of? Address
@@ -666,9 +674,9 @@ class CCompiler < C::Compiler
666
674
 
667
675
  if ft.kind_of? C::Function and ft.varargs and @state.args_space == 0
668
676
  # gcc stores here the nr of xmm args passed, real args are passed the standard way
669
- # TODO check visualstudio/ms ABI
670
677
  instr 'xor', rax, rax
671
678
  inuse rax
679
+ regargs_unuse << rax
672
680
  end
673
681
 
674
682
 
@@ -699,6 +707,7 @@ class CCompiler < C::Compiler
699
707
  else
700
708
  instr 'pop', Reg.new(reg, 64)
701
709
  end
710
+ inuse getreg(reg)
702
711
  }
703
712
  retreg
704
713
  end
@@ -750,8 +759,10 @@ class CCompiler < C::Compiler
750
759
 
751
760
  case op
752
761
  when 'add', 'sub', 'and', 'or', 'xor'
753
- r = make_volatile(r, type) if l.kind_of? ModRM and r.kind_of? ModRM
762
+ r = make_volatile(r, type) if l.kind_of?(ModRM) and r.kind_of?(ModRM)
763
+ r = make_volatile(r, type) if r.kind_of?(ModRM) and r.sz != l.sz # add rax, word [moo]
754
764
  unuse r
765
+ r = Reg.new(r.val, l.sz) if r.kind_of?(Reg) and l.kind_of?(ModRM) and l.sz and l.sz != r.sz # add byte ptr [rax], bl
755
766
  instr op, l, i_to_i32(r)
756
767
  when 'shr', 'sar', 'shl'
757
768
  if r.kind_of? Expression
@@ -780,6 +791,7 @@ class CCompiler < C::Compiler
780
791
  end
781
792
  instr 'mov', l, ll
782
793
  else
794
+ r = make_volatile(r, type) if r.kind_of?(ModRM) and r.sz != l.sz
783
795
  instr 'imul', l, r
784
796
  end
785
797
  unuse r
@@ -866,18 +878,21 @@ class CCompiler < C::Compiler
866
878
  l = c_cexpr_inner(expr.lexpr)
867
879
  r = c_cexpr_inner(expr.rexpr)
868
880
  r = make_volatile(r, expr.type) if r.kind_of? ModRM and l.kind_of? ModRM
881
+ r = make_volatile(r, expr.type) if r.kind_of?(ModRM) and r.sz != l.sz
882
+ l = make_volatile(l, expr.type) if l.kind_of?(ModRM) and r.kind_of?(Reg) and r.sz != l.sz
869
883
  if l.kind_of? Expression
870
884
  o = { :< => :>, :> => :<, :>= => :<=, :<= => :>= }[o] || o
871
885
  l, r = r, l
872
886
  end
873
- unuse l, r
874
887
  if expr.lexpr.type.integral? or expr.lexpr.type.pointer?
875
- r = Reg.new(r.val, l.sz) if r.kind_of? Reg and r.sz != l.sz # XXX
876
- instr 'cmp', l, i_to_i32(r)
888
+ rr = i_to_i32(r)
889
+ rr = Reg.new(rr.val, l.sz) if rr.kind_of? Reg and rr.sz != l.sz # XXX
890
+ instr 'cmp', l, rr
877
891
  elsif expr.lexpr.type.float?
878
892
  raise 'float unhandled'
879
893
  else raise 'bad comparison ' + expr.to_s
880
894
  end
895
+ unuse l, r
881
896
  op = 'j' + getcc(o, expr.lexpr.type)
882
897
  instr op, Expression[target]
883
898
  when :'!'
@@ -1011,10 +1026,6 @@ class CCompiler < C::Compiler
1011
1026
 
1012
1027
  def c_program_epilog
1013
1028
  end
1014
-
1015
- def check_reserved_name(var)
1016
- Reg.s_to_i[var.name] or super(var)
1017
- end
1018
1029
  end
1019
1030
 
1020
1031
  def new_ccompiler(parser, exe=ExeFormat.new)
@@ -4,7 +4,7 @@
4
4
  # Licence is LGPL, see LICENCE in the top-level directory
5
5
 
6
6
 
7
- require 'metasm/x86_64/opcodes'
7
+ require 'metasm/cpu/x86_64/opcodes'
8
8
 
9
9
  module Metasm
10
10
  class X86_64
@@ -15,7 +15,7 @@ class X86_64
15
15
  @dbg_register_flags ||= :rflags
16
16
  end
17
17
 
18
- def dbg_register_list
18
+ def dbg_register_list
19
19
  @dbg_register_list ||= [:rax, :rbx, :rcx, :rdx, :rsi, :rdi, :rbp, :rsp, :r8, :r9, :r10, :r11, :r12, :r13, :r14, :r15, :rip]
20
20
  end
21
21
 
@@ -40,10 +40,10 @@ class X86_64
40
40
  end
41
41
  def dbg_func_arg_set(dbg, argnr, arg)
42
42
  if dbg.class.name =~ /win/i
43
- list = []
43
+ list = [:rcx, :rdx, :r8, :r9]
44
44
  off = 0x20
45
45
  else
46
- list = []
46
+ list = [:rdi, :rsi, :rdx, :rcx, :r8, :r9]
47
47
  off = 0
48
48
  end
49
49
  if r = list[argnr]
@@ -4,7 +4,7 @@
4
4
  # Licence is LGPL, see LICENCE in the top-level directory
5
5
 
6
6
 
7
- require 'metasm/x86_64/opcodes'
7
+ require 'metasm/cpu/x86_64/opcodes'
8
8
  require 'metasm/decode'
9
9
 
10
10
  module Metasm
@@ -15,7 +15,7 @@ class X86_64
15
15
  rm = byte & 7
16
16
 
17
17
  if m == 3
18
- rm |= 8 if pfx[:rex_b]
18
+ rm |= 8 if pfx[:rex_b] and (regclass != SimdReg or opsz != 64) # mm8 -> mm0
19
19
  return regclass.new(rm, opsz)
20
20
  end
21
21
 
@@ -33,7 +33,12 @@ class X86_64
33
33
  ii |= 8 if pfx[:rex_x]
34
34
  if ii != 4
35
35
  s = 1 << ((sib >> 6) & 3)
36
- i = Reg.new(ii, adsz)
36
+ if pfx[:mrmvex]
37
+ i = SimdReg.new(ii, pfx[:mrmvex])
38
+ else
39
+ i = Reg.new(ii, adsz)
40
+ end
41
+
37
42
  end
38
43
 
39
44
  bb = sib & 7
@@ -62,6 +67,7 @@ class X86_64
62
67
  imm = Expression[imm.reduce & ((1 << adsz) - 1)]
63
68
  end
64
69
 
70
+ opsz = pfx[:argsz] if pfx[:argsz]
65
71
  new adsz, opsz, s, i, b, imm, seg
66
72
  end
67
73
  end
@@ -103,7 +109,26 @@ class X86_64
103
109
  v
104
110
  }
105
111
 
106
- opsz = op.props[:argsz] || (pfx[:rex_w] ? 64 : (pfx[:opsz] ? 16 : (op.props[:auto64] ? 64 : 32)))
112
+ pfx[:rex_r] = 1 if op.fields[:vex_r] and field_val[:vex_r] == 0
113
+ pfx[:rex_b] = 1 if op.fields[:vex_b] and field_val[:vex_b] == 0
114
+ pfx[:rex_x] = 1 if op.fields[:vex_x] and field_val[:vex_x] == 0
115
+ pfx[:rex_w] = 1 if op.fields[:vex_w] and field_val[:vex_w] == 1
116
+ di.instruction.prefix = pfx if not di.instruction.prefix and not pfx.empty? # for opsz(di) + vex_w
117
+
118
+ case op.props[:needpfx]
119
+ when 0x66; pfx.delete :opsz
120
+ when 0x67; pfx.delete :adsz
121
+ when 0xF2, 0xF3; pfx.delete :rep
122
+ end
123
+
124
+ if op.props[:setip] and not op.props[:stopexec] and pfx[:seg]
125
+ case pfx.delete(:seg).val
126
+ when 1; pfx[:jmphint] = 'hintnojmp'
127
+ when 3; pfx[:jmphint] = 'hintjmp'
128
+ end
129
+ end
130
+
131
+ opsz = op.props[:argsz] || opsz(di)
107
132
  adsz = pfx[:adsz] ? 32 : 64
108
133
  mmxsz = (op.props[:xmmx] && pfx[:opsz]) ? 128 : 64
109
134
 
@@ -114,21 +139,29 @@ class X86_64
114
139
  when :eeed; DbgReg.new field_val_r[a]
115
140
  when :eeet; TstReg.new field_val_r[a]
116
141
  when :seg2, :seg2A, :seg3, :seg3A; SegReg.new field_val[a]
117
- when :regmmx; SimdReg.new field_val_r[a], mmxsz
142
+ when :regmmx; SimdReg.new field_val[a], mmxsz # rex_r ignored
118
143
  when :regxmm; SimdReg.new field_val_r[a], 128
144
+ when :regymm; SimdReg.new field_val_r[a], 256
119
145
 
120
146
  when :farptr; Farptr.decode edata, @endianness, opsz
121
147
  when :i8, :u8, :i16, :u16, :i32, :u32, :i64, :u64; Expression[edata.decode_imm(a, @endianness)]
122
148
  when :i # 64bit constants are sign-extended from :i32
123
149
  type = (opsz == 64 ? op.props[:imm64] ? :a64 : :i32 : "#{op.props[:unsigned_imm] ? 'a' : 'i'}#{opsz}".to_sym )
124
- v = edata.decode_imm(type, @endianness)
150
+ v = edata.decode_imm(type, @endianness)
125
151
  v &= 0xffff_ffff_ffff_ffff if opsz == 64 and op.props[:unsigned_imm] and v.kind_of? Integer
126
152
  Expression[v]
127
153
 
128
- when :mrm_imm; ModRM.new(adsz, opsz, nil, nil, nil, Expression[edata.decode_imm("a#{adsz}".to_sym, @endianness)], pfx[:seg])
129
- when :modrm, :modrmA; ModRM.decode edata, field_val[a], @endianness, adsz, opsz, pfx[:seg], Reg, pfx
130
- when :modrmmmx; ModRM.decode edata, field_val[:modrm], @endianness, adsz, mmxsz, pfx[:seg], SimdReg, pfx
131
- when :modrmxmm; ModRM.decode edata, field_val[:modrm], @endianness, adsz, 128, pfx[:seg], SimdReg, pfx
154
+ when :mrm_imm; ModRM.new(adsz, opsz, nil, nil, nil, Expression[edata.decode_imm("a#{adsz}".to_sym, @endianness)], pfx.delete(:seg))
155
+ when :modrm; ModRM.decode edata, field_val[:modrm], @endianness, adsz, opsz, pfx.delete(:seg), Reg, pfx
156
+ when :modrmmmx; ModRM.decode edata, field_val[:modrm], @endianness, adsz, mmxsz, pfx.delete(:seg), SimdReg, pfx.merge(:argsz => op.props[:argsz])
157
+ when :modrmxmm; ModRM.decode edata, field_val[:modrm], @endianness, adsz, 128, pfx.delete(:seg), SimdReg, pfx.merge(:argsz => op.props[:argsz], :mrmvex => op.props[:mrmvex])
158
+ when :modrmymm; ModRM.decode edata, field_val[:modrm], @endianness, adsz, 256, pfx.delete(:seg), SimdReg, pfx.merge(:argsz => op.props[:argsz], :mrmvex => op.props[:mrmvex])
159
+
160
+ when :vexvreg; Reg.new((field_val[:vex_vvvv] ^ 0xf), opsz)
161
+ when :vexvxmm; SimdReg.new((field_val[:vex_vvvv] ^ 0xf), 128)
162
+ when :vexvymm; SimdReg.new((field_val[:vex_vvvv] ^ 0xf), 256)
163
+ when :i4xmm; SimdReg.new(edata.decode_imm(:u8, @endianness) >> 4, 128)
164
+ when :i4ymm; SimdReg.new(edata.decode_imm(:u8, @endianness) >> 4, 256)
132
165
 
133
166
  when :regfp; FpReg.new field_val[a]
134
167
  when :imm_val1; Expression[1]
@@ -143,6 +176,8 @@ class X86_64
143
176
 
144
177
  di.bin_length += edata.ptr - before_ptr
145
178
 
179
+ return if edata.ptr > edata.length
180
+
146
181
  if op.name == 'movsx' or op.name == 'movzx' or op.name == 'movsxd'
147
182
  if op.name == 'movsxd'
148
183
  di.instruction.args[1].sz = 32
@@ -158,12 +193,13 @@ class X86_64
158
193
  else
159
194
  di.instruction.args[0].sz = 32
160
195
  end
196
+ elsif op.name == 'crc32'
197
+ di.instruction.args[0].sz = 32
161
198
  end
162
199
 
163
200
  # sil => bh
164
201
  di.instruction.args.each { |a| a.val += 12 if a.kind_of? Reg and a.sz == 8 and not pfx[:rex] and a.val >= 4 and a.val <= 8 }
165
202
 
166
- pfx.delete :seg
167
203
  case pfx.delete(:rep)
168
204
  when :nz
169
205
  if di.opcode.props[:strop]
@@ -195,18 +231,24 @@ class X86_64
195
231
  di
196
232
  end
197
233
 
198
- def opsz(di)
234
+ def opsz(di, op=nil)
199
235
  if di and di.instruction.prefix and di.instruction.prefix[:rex_w]; 64
200
- elsif di and di.instruction.prefix and di.instruction.prefix[:opsz]; 16
201
- elsif di and di.opcode.props[:auto64]; 64
236
+ elsif di and di.instruction.prefix and di.instruction.prefix[:opsz] and (op || di.opcode).props[:needpfx] != 0x66; 16
237
+ elsif di and (op || di.opcode).props[:auto64]; 64
202
238
  else 32
203
239
  end
204
240
  end
205
241
 
242
+ def adsz(di, op=nil)
243
+ if di and di.instruction.prefix and di.instruction.prefix[:adsz] and (op || di.opcode).props[:needpfx] != 0x67; 32
244
+ else 64
245
+ end
246
+ end
247
+
206
248
  def register_symbols
207
249
  [:rax, :rcx, :rdx, :rbx, :rsp, :rbp, :rsi, :rdi, :r8, :r9, :r10, :r11, :r12, :r13, :r14, :r15]
208
250
  end
209
-
251
+
210
252
  # returns a DecodedFunction from a parsed C function prototype
211
253
  def decode_c_function_prototype(cp, sym, orig=nil)
212
254
  sym = cp.toplevel.symbol[sym] if sym.kind_of?(::String)
@@ -4,7 +4,7 @@
4
4
  # Licence is LGPL, see LICENCE in the top-level directory
5
5
 
6
6
 
7
- require 'metasm/x86_64/opcodes'
7
+ require 'metasm/cpu/x86_64/opcodes'
8
8
  require 'metasm/encode'
9
9
 
10
10
  module Metasm
@@ -64,7 +64,7 @@ class X86_64
64
64
  # sib
65
65
  or_bits[4]
66
66
 
67
- @b, @i = @i, @b if @s == 1 and (@i.val_enc == 4 or @b.val_enc == 5)
67
+ @b, @i = @i, @b if @s == 1 and @i.kind_of?(Reg) and (@i.val_enc == 4 or @b.val_enc == 5)
68
68
 
69
69
  raise EncodeError, "Invalid ModRM #{self}" if @i.val == 4
70
70
 
@@ -116,23 +116,30 @@ class X86_64
116
116
  case k
117
117
  when :jmp; {:jmp => 0x3e, :nojmp => 0x2e}[v]
118
118
  when :lock; 0xf0
119
- when :rep; {'repnz' => 0xf2, 'repz' => 0xf3, 'rep' => 0xf2}[v] # TODO
119
+ when :rep; {'repnz' => 0xf2, 'repz' => 0xf3, 'rep' => 0xf2}[v]
120
+ when :jmphint; {'hintjmp' => 0x3e, 'hintnojmp' => 0x2e}[v]
121
+ when :seg; [0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65][v.val]
120
122
  end
121
123
  }.compact.pack 'C*'
122
- pfx << op.props[:needpfx] if op.props[:needpfx]
123
124
 
124
- rex_w = rex_r = rex_x = rex_b = nil
125
+ rex_w = rex_r = rex_x = rex_b = 0
125
126
  if op.name == 'movsx' or op.name == 'movzx' or op.name == 'movsxd'
126
127
  case i.args[0].sz
127
128
  when 64; rex_w = 1
128
129
  when 32
129
130
  when 16; pfx << 0x66
130
131
  end
132
+ elsif op.name == 'crc32'
133
+ case i.args[1].sz
134
+ when 64; rex_w = 1
135
+ when 32;
136
+ when 16; pfx << 0x66
137
+ end
131
138
  else
132
139
  opsz = op.props[:argsz] || i.prefix[:sz]
133
140
  oi.each { |oa, ia|
134
141
  case oa
135
- when :reg, :reg_eax, :modrm, :modrmA, :mrm_imm
142
+ when :reg, :reg_eax, :modrm, :mrm_imm
136
143
  raise EncodeError, "Incompatible arg size in #{i}" if ia.sz and opsz and opsz != ia.sz
137
144
  opsz = ia.sz
138
145
  end
@@ -140,7 +147,7 @@ class X86_64
140
147
  opsz ||= 64 if op.props[:auto64]
141
148
  opsz = op.props[:opsz] if op.props[:opsz] # XXX ?
142
149
  case opsz
143
- when 64; rex_w = 1 if not op.props[:auto64]
150
+ when 64; rex_w = 1 if not op.props[:auto64] and (not op.props[:argsz] or op.props[:opsz] == 64)
144
151
  when 32; raise EncodeError, "Incompatible arg size in #{i}" if op.props[:auto64]
145
152
  when 16; pfx << 0x66
146
153
  end
@@ -168,25 +175,27 @@ class X86_64
168
175
  when :reg
169
176
  set_field[oa, ia.val_enc]
170
177
  if op.fields[:reg][1] == 3
171
- rex_r = ia.val_rex
178
+ rex_r = ia.val_rex || 0
172
179
  else
173
- rex_b = ia.val_rex
180
+ rex_b = ia.val_rex || 0
174
181
  end
175
- when :seg3, :seg3A, :seg2, :seg2A, :eeec, :eeed, :eeet, :regfp, :regxmm, :regmmx
182
+ when :seg3, :seg3A, :seg2, :seg2A, :eeec, :eeed, :eeet, :regfp, :regmmx, :regxmm, :regymm
176
183
  set_field[oa, ia.val & 7]
177
184
  rex_r = 1 if ia.val > 7
178
185
  pfx << 0x66 if oa == :regmmx and op.props[:xmmx] and ia.sz == 128
186
+ when :vexvreg, :vexvxmm, :vexvymm
187
+ set_field[:vex_vvvv, ia.val ^ 0xf]
179
188
  when :imm_val1, :imm_val3, :reg_cl, :reg_eax, :reg_dx, :regfp0
180
189
  # implicit
181
- when :modrm, :modrmA, :modrmmmx, :modrmxmm
190
+ when :modrm, :modrmmmx, :modrmxmm, :modrmymm
182
191
  # postpone, but we must set rex now
183
192
  case ia
184
193
  when ModRM
185
194
  ia.encode(0, @endianness) # could swap b/i
186
- rex_x = ia.i.val_rex if ia.i
187
- rex_b = ia.b.val_rex if ia.b
195
+ rex_x = ia.i.val_rex || 0 if ia.i
196
+ rex_b = ia.b.val_rex || 0 if ia.b
188
197
  when Reg
189
- rex_b = ia.val_rex
198
+ rex_b = ia.val_rex || 0
190
199
  else
191
200
  rex_b = ia.val >> 3
192
201
  end
@@ -196,7 +205,7 @@ class X86_64
196
205
  end
197
206
  }
198
207
 
199
- if !(op.args & [:modrm, :modrmA, :modrmxmm, :modrmmmx]).empty?
208
+ if !(op.args & [:modrm, :modrmmmx, :modrmxmm, :modrmymm]).empty?
200
209
  # reg field of modrm
201
210
  regval = (base[-1] >> 3) & 7
202
211
  base.pop
@@ -210,20 +219,26 @@ class X86_64
210
219
  postponed.first[1] = Expression[target, :-, postlabel]
211
220
  end
212
221
 
213
- if rex_w == 1 or rex_r == 1 or rex_b == 1 or rex_x == 1 or i.args.grep(Reg).find { |r| r.sz == 8 and r.val >= 4 and r.val < 8 }
214
- rex ||= 0x40
215
- rex |= 1 if rex_b.to_i > 0
216
- rex |= 2 if rex_x.to_i > 0
217
- rex |= 4 if rex_r.to_i > 0
218
- rex |= 8 if rex_w.to_i > 0
222
+ pfx << op.props[:needpfx] if op.props[:needpfx]
223
+
224
+ if op.fields[:vex_r]
225
+ set_field[:vex_r, rex_r ^ 1]
226
+ set_field[:vex_x, rex_x ^ 1] if op.fields[:vex_x]
227
+ set_field[:vex_b, rex_b ^ 1] if op.fields[:vex_b]
228
+ set_field[:vex_w, rex_w] if op.fields[:vex_w]
229
+ elsif rex_r + rex_x + rex_b + rex_w >= 1 or i.args.grep(Reg).find { |r| r.sz == 8 and r.val >= 4 and r.val < 8 }
230
+ rex = 0x40
231
+ rex |= 1 if rex_b == 1
232
+ rex |= 2 if rex_x == 1
233
+ rex |= 4 if rex_r == 1
234
+ rex |= 8 if rex_w == 1
235
+ pfx << rex
219
236
  end
220
- pfx << rex if rex
221
237
  ret = EncodedData.new(pfx + base.pack('C*'))
222
238
 
223
239
  postponed.each { |oa, ia|
224
240
  case oa
225
- when :farptr; ed = ia.encode(@endianness, "a#{opsz}".to_sym)
226
- when :modrm, :modrmA, :modrmmmx, :modrmxmm
241
+ when :modrm, :modrmmmx, :modrmxmm, :modrmymm
227
242
  if ia.kind_of? ModRM
228
243
  ed = ia.encode(regval, @endianness)
229
244
  if ed.kind_of?(::Array)
@@ -243,8 +258,22 @@ class X86_64
243
258
  when :mrm_imm; ed = ia.imm.encode("a#{op.props[:adsz] || 64}".to_sym, @endianness)
244
259
  when :i8, :u8, :i16, :u16, :i32, :u32, :i64, :u64; ed = ia.encode(oa, @endianness)
245
260
  when :i
246
- type = (opsz == 64 ? op.props[:imm64] ? :a64 : :i32 : "#{op.props[:unsigned_imm] ? 'a' : 'i'}#{opsz}".to_sym)
247
- ed = ia.encode(type, @endianness)
261
+ type = if opsz == 64
262
+ if op.props[:imm64]
263
+ :a64
264
+ else
265
+ if _ia = ia.reduce and _ia.kind_of?(Integer) and _ia > 0 and (_ia >> 63) == 1
266
+ # handle 0xffffffff_ffffffff -> -1, which should fit in i32
267
+ ia = Expression[_ia - (1 << 64)]
268
+ end
269
+ :i32
270
+ end
271
+ else
272
+ "a#{opsz}".to_sym
273
+ end
274
+ ed = ia.encode(type, @endianness)
275
+ when :i4xmm, :i4ymm
276
+ ed = ia.val << 4 # u8
248
277
  else raise SyntaxError, "Internal error: want to encode field #{oa.inspect} as arg in #{i}"
249
278
  end
250
279