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.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.hgtags +3 -0
- data/Gemfile +1 -0
- data/INSTALL +61 -0
- data/LICENCE +458 -0
- data/README +29 -21
- data/Rakefile +10 -0
- data/TODO +10 -12
- data/doc/code_organisation.txt +2 -0
- data/doc/core/DynLdr.txt +247 -0
- data/doc/core/ExeFormat.txt +43 -0
- data/doc/core/Expression.txt +220 -0
- data/doc/core/GNUExports.txt +27 -0
- data/doc/core/Ia32.txt +236 -0
- data/doc/core/SerialStruct.txt +108 -0
- data/doc/core/VirtualString.txt +145 -0
- data/doc/core/WindowsExports.txt +61 -0
- data/doc/core/index.txt +1 -0
- data/doc/style.css +6 -3
- data/doc/usage/debugger.txt +327 -0
- data/doc/usage/index.txt +1 -0
- data/doc/use_cases.txt +2 -2
- data/metasm.gemspec +22 -0
- data/{lib/metasm.rb → metasm.rb} +11 -3
- data/{lib/metasm → metasm}/compile_c.rb +13 -7
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +425 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
- data/metasm/cpu/arm/opcodes.rb +324 -0
- data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
- data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
- data/metasm/cpu/arm64.rb +15 -0
- data/metasm/cpu/arm64/debug.rb +38 -0
- data/metasm/cpu/arm64/decode.rb +289 -0
- data/metasm/cpu/arm64/encode.rb +41 -0
- data/metasm/cpu/arm64/main.rb +105 -0
- data/metasm/cpu/arm64/opcodes.rb +232 -0
- data/metasm/cpu/arm64/parse.rb +20 -0
- data/metasm/cpu/arm64/render.rb +95 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
- data/metasm/cpu/bpf/decode.rb +142 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +41 -0
- data/metasm/cpu/cy16.rb +9 -0
- data/metasm/cpu/cy16/decode.rb +253 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +41 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
- data/metasm/cpu/mips.rb +14 -0
- data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
- data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
- data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
- data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
- data/metasm/cpu/msp430/decode.rb +247 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
- data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
- data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
- data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
- data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
- data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
- data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +136 -0
- data/metasm/cpu/python/main.rb +36 -0
- data/metasm/cpu/python/opcodes.rb +180 -0
- data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
- data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
- data/metasm/cpu/x86_64/opcodes.rb +136 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +313 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +59 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
- data/{lib/metasm → metasm}/decode.rb +35 -4
- data/{lib/metasm → metasm}/decompile.rb +15 -16
- data/{lib/metasm → metasm}/disassemble.rb +201 -45
- data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
- data/{lib/metasm → metasm}/dynldr.rb +220 -133
- data/{lib/metasm → metasm}/encode.rb +10 -1
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
- data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
- data/metasm/exe_format/pyc.rb +167 -0
- data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
- data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
- data/metasm/exe_format/shellcode_rwx.rb +114 -0
- data/metasm/exe_format/swf.rb +205 -0
- data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
- data/metasm/exe_format/zip.rb +335 -0
- data/metasm/gui.rb +13 -0
- data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
- data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
- data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1695 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +93 -27
- data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
- data/{lib/metasm → metasm}/gui/qt.rb +12 -2
- data/{lib/metasm → metasm}/gui/win32.rb +179 -42
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +389 -264
- data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
- data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
- data/{lib/metasm → metasm}/os/linux.rb +628 -151
- data/metasm/os/main.rb +330 -0
- data/{lib/metasm → metasm}/os/windows.rb +132 -42
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +26 -24
- data/{lib/metasm → metasm}/parse_c.rb +221 -116
- data/{lib/metasm → metasm}/preprocessor.rb +55 -40
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +2 -1
- data/misc/lint.rb +58 -0
- data/misc/txt2html.rb +9 -7
- data/samples/bindiff.rb +3 -4
- data/samples/dasm-plugins/bindiff.rb +15 -0
- data/samples/dasm-plugins/bookmark.rb +133 -0
- data/samples/dasm-plugins/c_constants.rb +57 -0
- data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
- data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
- data/samples/dasm-plugins/dasm_all.rb +70 -0
- data/samples/dasm-plugins/demangle_cpp.rb +31 -0
- data/samples/dasm-plugins/deobfuscate.rb +251 -0
- data/samples/dasm-plugins/dump_text.rb +35 -0
- data/samples/dasm-plugins/export_graph_svg.rb +86 -0
- data/samples/dasm-plugins/findgadget.rb +75 -0
- data/samples/dasm-plugins/hl_opcode.rb +32 -0
- data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
- data/samples/dasm-plugins/imm2off.rb +34 -0
- data/samples/dasm-plugins/match_libsigs.rb +93 -0
- data/samples/dasm-plugins/patch_file.rb +95 -0
- data/samples/dasm-plugins/scanfuncstart.rb +36 -0
- data/samples/dasm-plugins/scanxrefs.rb +26 -0
- data/samples/dasm-plugins/selfmodify.rb +197 -0
- data/samples/dasm-plugins/stringsxrefs.rb +28 -0
- data/samples/dasmnavig.rb +1 -1
- data/samples/dbg-apihook.rb +24 -9
- data/samples/dbg-plugins/heapscan.rb +283 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
- data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
- data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
- data/samples/dbg-plugins/heapscan/winheap.h +174 -0
- data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
- data/samples/dbg-plugins/trace_func.rb +214 -0
- data/samples/disassemble-gui.rb +35 -5
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +12 -3
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +175 -381
- data/samples/metasm-shell.rb +1 -2
- data/samples/peldr.rb +2 -2
- data/tests/all.rb +1 -1
- data/tests/arc.rb +26 -0
- data/tests/dynldr.rb +22 -4
- data/tests/expression.rb +55 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +79 -26
- data/tests/mips.rb +9 -2
- data/tests/x86_64.rb +66 -18
- metadata +330 -218
- data/lib/metasm/arm/opcodes.rb +0 -177
- data/lib/metasm/gui.rb +0 -23
- data/lib/metasm/gui/dasm_graph.rb +0 -1354
- data/lib/metasm/ia32.rb +0 -14
- data/lib/metasm/ia32/opcodes.rb +0 -873
- data/lib/metasm/ppc/parse.rb +0 -52
- data/lib/metasm/x86_64.rb +0 -12
- data/lib/metasm/x86_64/opcodes.rb +0 -118
- data/samples/gdbclient.rb +0 -583
- 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 '
|
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).
|
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?
|
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
|
-
|
876
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
-
|
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
|
129
|
-
when :modrm
|
130
|
-
when :modrmmmx; ModRM.decode edata, field_val[:modrm], @endianness, adsz, mmxsz, pfx
|
131
|
-
when :modrmxmm; ModRM.decode edata, field_val[:modrm], @endianness, adsz, 128, 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]
|
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 =
|
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, :
|
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, :
|
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, :
|
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, :
|
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
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
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 :
|
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 =
|
247
|
-
|
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
|
|