metasm 1.0.3 → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +3 -0
- data.tar.gz.sig +0 -0
- data/Gemfile +3 -2
- data/metasm.gemspec +3 -2
- data/metasm.rb +4 -1
- data/metasm/compile_c.rb +2 -2
- data/metasm/cpu/arc/decode.rb +0 -21
- data/metasm/cpu/arc/main.rb +4 -4
- data/metasm/cpu/arm/decode.rb +1 -5
- data/metasm/cpu/arm/main.rb +3 -3
- data/metasm/cpu/arm64/decode.rb +2 -6
- data/metasm/cpu/arm64/main.rb +5 -5
- data/metasm/cpu/bpf/decode.rb +3 -35
- data/metasm/cpu/bpf/main.rb +5 -5
- data/metasm/cpu/bpf/render.rb +1 -12
- data/metasm/cpu/cy16/decode.rb +0 -6
- data/metasm/cpu/cy16/main.rb +3 -3
- data/metasm/cpu/cy16/render.rb +0 -11
- data/metasm/cpu/dalvik/decode.rb +4 -26
- data/metasm/cpu/dalvik/main.rb +20 -2
- data/metasm/cpu/dalvik/opcodes.rb +3 -2
- data/metasm/cpu/{mips/compile_c.rb → ebpf.rb} +5 -2
- data/metasm/cpu/ebpf/debug.rb +61 -0
- data/metasm/cpu/ebpf/decode.rb +142 -0
- data/metasm/cpu/ebpf/main.rb +58 -0
- data/metasm/cpu/ebpf/opcodes.rb +97 -0
- data/metasm/cpu/ebpf/render.rb +36 -0
- data/metasm/cpu/ia32/debug.rb +39 -1
- data/metasm/cpu/ia32/decode.rb +111 -90
- data/metasm/cpu/ia32/decompile.rb +45 -37
- data/metasm/cpu/ia32/main.rb +10 -0
- data/metasm/cpu/ia32/parse.rb +6 -0
- data/metasm/cpu/mcs51/decode.rb +1 -1
- data/metasm/cpu/mcs51/main.rb +11 -0
- data/metasm/cpu/mips/decode.rb +8 -18
- data/metasm/cpu/mips/main.rb +3 -3
- data/metasm/cpu/mips/opcodes.rb +1 -1
- data/metasm/cpu/msp430/decode.rb +2 -6
- data/metasm/cpu/msp430/main.rb +3 -3
- data/metasm/cpu/openrisc.rb +11 -0
- data/metasm/cpu/openrisc/debug.rb +106 -0
- data/metasm/cpu/openrisc/decode.rb +182 -0
- data/metasm/cpu/openrisc/decompile.rb +350 -0
- data/metasm/cpu/openrisc/main.rb +70 -0
- data/metasm/cpu/openrisc/opcodes.rb +109 -0
- data/metasm/cpu/openrisc/render.rb +37 -0
- data/metasm/cpu/ppc/decode.rb +0 -25
- data/metasm/cpu/ppc/main.rb +6 -6
- data/metasm/cpu/ppc/opcodes.rb +3 -4
- data/metasm/cpu/python/decode.rb +0 -20
- data/metasm/cpu/python/main.rb +1 -1
- data/metasm/cpu/sh4/decode.rb +2 -6
- data/metasm/cpu/sh4/main.rb +25 -23
- data/metasm/cpu/st20/decode.rb +0 -7
- data/metasm/cpu/webasm.rb +11 -0
- data/metasm/cpu/webasm/debug.rb +31 -0
- data/metasm/cpu/webasm/decode.rb +321 -0
- data/metasm/cpu/webasm/decompile.rb +386 -0
- data/metasm/cpu/webasm/encode.rb +104 -0
- data/metasm/cpu/webasm/main.rb +81 -0
- data/metasm/cpu/webasm/opcodes.rb +214 -0
- data/metasm/cpu/x86_64/compile_c.rb +13 -9
- data/metasm/cpu/x86_64/parse.rb +1 -1
- data/metasm/cpu/z80/decode.rb +0 -27
- data/metasm/cpu/z80/main.rb +3 -3
- data/metasm/cpu/z80/render.rb +0 -11
- data/metasm/debug.rb +43 -8
- data/metasm/decode.rb +62 -14
- data/metasm/decompile.rb +793 -466
- data/metasm/disassemble.rb +188 -131
- data/metasm/disassemble_api.rb +30 -17
- data/metasm/dynldr.rb +2 -2
- data/metasm/encode.rb +8 -2
- data/metasm/exe_format/autoexe.rb +2 -0
- data/metasm/exe_format/coff.rb +21 -3
- data/metasm/exe_format/coff_decode.rb +12 -0
- data/metasm/exe_format/coff_encode.rb +6 -3
- data/metasm/exe_format/dex.rb +13 -3
- data/metasm/exe_format/elf.rb +12 -2
- data/metasm/exe_format/elf_decode.rb +59 -1
- data/metasm/exe_format/main.rb +2 -0
- data/metasm/exe_format/mz.rb +1 -0
- data/metasm/exe_format/pe.rb +25 -3
- data/metasm/exe_format/wasm.rb +402 -0
- data/metasm/gui/dasm_decomp.rb +171 -95
- data/metasm/gui/dasm_graph.rb +61 -2
- data/metasm/gui/dasm_hex.rb +2 -2
- data/metasm/gui/dasm_main.rb +45 -19
- data/metasm/gui/debug.rb +13 -4
- data/metasm/gui/gtk.rb +12 -4
- data/metasm/main.rb +108 -103
- data/metasm/os/emulator.rb +175 -0
- data/metasm/os/main.rb +11 -6
- data/metasm/parse.rb +23 -12
- data/metasm/parse_c.rb +189 -135
- data/metasm/preprocessor.rb +16 -1
- data/misc/openrisc-parser.rb +79 -0
- data/samples/dasm-plugins/scanxrefs.rb +6 -4
- data/samples/dasm-plugins/selfmodify.rb +8 -8
- data/samples/dbg-plugins/trace_func.rb +1 -1
- data/samples/disassemble-gui.rb +14 -3
- data/samples/emubios.rb +251 -0
- data/samples/emudbg.rb +127 -0
- data/samples/lindebug.rb +79 -78
- data/samples/metasm-shell.rb +8 -8
- data/tests/all.rb +1 -1
- data/tests/expression.rb +2 -0
- data/tests/graph_layout.rb +1 -1
- data/tests/ia32.rb +1 -0
- data/tests/mips.rb +1 -1
- data/tests/preprocessor.rb +18 -0
- metadata +124 -6
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,104 @@
|
|
|
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
|
+
|
|
7
|
+
require 'metasm/cpu/webasm/opcodes'
|
|
8
|
+
require 'metasm/parse'
|
|
9
|
+
|
|
10
|
+
module Metasm
|
|
11
|
+
class WebAsm
|
|
12
|
+
def parse_argument(lexer)
|
|
13
|
+
lexer = AsmPreprocessor.new(lexer) if lexer.kind_of? String
|
|
14
|
+
lexer.skip_space
|
|
15
|
+
return if not tok = lexer.readtok
|
|
16
|
+
|
|
17
|
+
if tok.type == :punct and tok.raw == '['
|
|
18
|
+
# Memref or BrTable
|
|
19
|
+
ary = []
|
|
20
|
+
loop do
|
|
21
|
+
# XXX empty array for BrTable ?
|
|
22
|
+
ary << parse_argument(lexer)
|
|
23
|
+
raise tok, 'bad ptr' if not ary.last.kind_of?(Expression)
|
|
24
|
+
lexer.skip_space
|
|
25
|
+
tok2 = lexer.readtok
|
|
26
|
+
if tok2 and tok2.type == :punct and tok2.raw == ']'
|
|
27
|
+
break
|
|
28
|
+
elsif not tok2 or tok2.type != :punct or tok2.raw != ','
|
|
29
|
+
raise tok, "unexpected #{tok2 ? 'eof' : tok2.raw}"
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
lexer.skip_space
|
|
33
|
+
tok2 = lexer.readtok
|
|
34
|
+
if tok2 and tok2.type == :string and tok2.raw == 'or'
|
|
35
|
+
# BrTable
|
|
36
|
+
df = parse_argument(lexer)
|
|
37
|
+
BrTable.new(ary, df)
|
|
38
|
+
else
|
|
39
|
+
raise tok, 'bad Memref/BrTable' if ary.length != 1
|
|
40
|
+
lexer.unreadtok(tok2) if tok2
|
|
41
|
+
Memref.new(ary[0])
|
|
42
|
+
end
|
|
43
|
+
elsif WasmFile::TYPE.index(tok.raw)
|
|
44
|
+
BlockSignature.new(WasmFile::TYPE.index(tok.raw))
|
|
45
|
+
else
|
|
46
|
+
lexer.unreadtok tok
|
|
47
|
+
expr = Expression.parse(lexer)
|
|
48
|
+
lexer.skip_space
|
|
49
|
+
expr
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def parse_arg_valid?(o, spec, arg)
|
|
54
|
+
spec and arg
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def parse_instruction_mnemonic(lexer)
|
|
58
|
+
return if not tok = lexer.readtok
|
|
59
|
+
tok = tok.dup
|
|
60
|
+
while ntok = lexer.nexttok and ntok.type == :punct and (ntok.raw == '.' or ntok.raw == '/')
|
|
61
|
+
tok.raw << lexer.readtok.raw
|
|
62
|
+
ntok = lexer.readtok
|
|
63
|
+
raise tok, 'invalid opcode name' if not ntok or ntok.type != :string
|
|
64
|
+
tok.raw << ntok.raw
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
raise tok, 'invalid opcode' if not opcode_list_byname[tok.raw]
|
|
68
|
+
tok
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def encode_uleb(val, signed=false)
|
|
72
|
+
# TODO labels ?
|
|
73
|
+
v = Expression[val].reduce
|
|
74
|
+
raise "need numeric value for #{val}" if not v.kind_of?(::Integer)
|
|
75
|
+
out = EncodedData.new
|
|
76
|
+
while v > 0x7f or v < -0x40 or (signed and v > 0x3f)
|
|
77
|
+
out << Expression[0x80 | (v&0x7f)].encode(:u8, @endianness)
|
|
78
|
+
v >>= 7
|
|
79
|
+
end
|
|
80
|
+
out << Expression[v & 0x7f].encode(:u8, @endianness)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def encode_instr_op(program, i, op)
|
|
84
|
+
ed = EncodedData.new([op.bin].pack('C*'))
|
|
85
|
+
op.args.zip(i.args).each { |oa, ia|
|
|
86
|
+
case oa
|
|
87
|
+
when :f32; ed << ia.encode(:u32, @endianness)
|
|
88
|
+
when :f64; ed << ia.encode(:u64, @endianness)
|
|
89
|
+
when :memoff; ed << encode_uleb(ia.off)
|
|
90
|
+
when :uleb; ed << encode_uleb(ia)
|
|
91
|
+
when :sleb; ed << encode_uleb(ia, true)
|
|
92
|
+
when :blocksig
|
|
93
|
+
ia = ia.id if ia.kind_of?(BlockSignature)
|
|
94
|
+
ed << encode_uleb(ia, true)
|
|
95
|
+
when :br_table
|
|
96
|
+
ed << encode_uleb(ia.ary.length)
|
|
97
|
+
ia.ary.each { |a| ed << encode_uleb(a) }
|
|
98
|
+
ed << encode_uleb(ia.default)
|
|
99
|
+
end
|
|
100
|
+
}
|
|
101
|
+
ed
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
2
|
+
# Copyright (C) 2006-2010 Yoann GUILLOT
|
|
3
|
+
#
|
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
|
+
|
|
6
|
+
require 'metasm/main'
|
|
7
|
+
|
|
8
|
+
module Metasm
|
|
9
|
+
|
|
10
|
+
class WebAsm < CPU
|
|
11
|
+
attr_accessor :wasm_file
|
|
12
|
+
def initialize(*args)
|
|
13
|
+
super()
|
|
14
|
+
@size = args.grep(Integer).first || 64
|
|
15
|
+
@wasm_file = args.grep(ExeFormat).first
|
|
16
|
+
@endianness = args.delete(:little) || args.delete(:big) || (@wasm_file ? @wasm_file.endianness : :little)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class Memref
|
|
20
|
+
attr_accessor :off
|
|
21
|
+
|
|
22
|
+
def initialize(off)
|
|
23
|
+
@off = Expression[off]
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def symbolic(di=nil)
|
|
27
|
+
sz = 8
|
|
28
|
+
off = Expression[:mem, :+, [@off]]
|
|
29
|
+
if di and di.opcode.name =~ /(32|64)\.(load|store)(8|16|32)?/
|
|
30
|
+
opsz, op, mode = $1, $2, $3
|
|
31
|
+
sz = mode ? mode.to_i/8 : opsz.to_i/8
|
|
32
|
+
stack_off = (op == 'store' ? [:opstack, :+, 8] : [:opstack])
|
|
33
|
+
off = Expression[Indirection[stack_off, 4], :+, off]
|
|
34
|
+
end
|
|
35
|
+
Indirection[off, sz, (di.address if di)]
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
include Renderable
|
|
39
|
+
def render
|
|
40
|
+
['[', @off, ']']
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class BrTable
|
|
45
|
+
attr_accessor :ary, :default
|
|
46
|
+
def initialize(ary, default)
|
|
47
|
+
@ary = ary
|
|
48
|
+
@default = default
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
include Renderable
|
|
52
|
+
def render
|
|
53
|
+
out = ['[']
|
|
54
|
+
@ary.each { |a| out << a << ', ' }
|
|
55
|
+
out.pop if out.length > 1
|
|
56
|
+
out << ']' << ' or ' << @default
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
class BlockSignature
|
|
61
|
+
attr_accessor :id
|
|
62
|
+
|
|
63
|
+
def initialize(id)
|
|
64
|
+
@id = id
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def symbolic(di=nil)
|
|
68
|
+
Expression[@id]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
include Renderable
|
|
72
|
+
def render
|
|
73
|
+
[WasmFile::TYPE.fetch(@id, Expression[@id])]
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def init_opcode_list
|
|
78
|
+
init
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
2
|
+
# Copyright (C) 2006-2010 Yoann GUILLOT
|
|
3
|
+
#
|
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
|
+
|
|
6
|
+
require 'metasm/cpu/webasm/main'
|
|
7
|
+
|
|
8
|
+
module Metasm
|
|
9
|
+
class WebAsm
|
|
10
|
+
def addop(name, bin, *args)
|
|
11
|
+
o = Opcode.new name, bin
|
|
12
|
+
|
|
13
|
+
args.each { |a|
|
|
14
|
+
if a == :mem
|
|
15
|
+
o.args << :uleb << :memoff
|
|
16
|
+
elsif @valid_props[a]
|
|
17
|
+
o.props[a] = true
|
|
18
|
+
else
|
|
19
|
+
o.args << a
|
|
20
|
+
end
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@opcode_list << o
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def init
|
|
27
|
+
@opcode_list = []
|
|
28
|
+
@valid_props = { :setip => true, :stopexec => true, :saveip => true }
|
|
29
|
+
|
|
30
|
+
addop 'unreachable', 0x00, :stopexec
|
|
31
|
+
addop 'nop', 0x01
|
|
32
|
+
addop 'block', 0x02, :blocksig # arg = signature (block_type)
|
|
33
|
+
addop 'loop', 0x03, :blocksig # ^
|
|
34
|
+
addop 'if', 0x04, :blocksig, :setip # ^
|
|
35
|
+
addop 'else', 0x05, :setip, :stopexec
|
|
36
|
+
addop 'end', 0x0b, :stopexec # end of function (default with no function context)
|
|
37
|
+
addop 'end', 0x0b # end of if/else/block/loop
|
|
38
|
+
addop 'br', 0x0c, :uleb, :setip, :stopexec # arg = depth to break up to
|
|
39
|
+
addop 'br_if', 0x0d, :uleb, :setip
|
|
40
|
+
addop 'br_table', 0x0e, :br_table, :setip, :stopexec
|
|
41
|
+
addop 'return', 0x0f, :stopexec
|
|
42
|
+
addop 'call', 0x10, :uleb, :setip, :saveip, :stopexec # function index
|
|
43
|
+
addop 'call_indirect', 0x11, :uleb, :uleb, :setip, :saveip, :stopexec # type index for target function signature ; table index where the function indexes come from (fixed 0)
|
|
44
|
+
|
|
45
|
+
addop 'drop', 0x1a
|
|
46
|
+
addop 'select', 0x1b
|
|
47
|
+
|
|
48
|
+
addop 'get_local', 0x20, :uleb
|
|
49
|
+
addop 'set_local', 0x21, :uleb
|
|
50
|
+
addop 'tee_local', 0x22, :uleb
|
|
51
|
+
addop 'get_global', 0x23, :uleb
|
|
52
|
+
addop 'set_global', 0x24, :uleb
|
|
53
|
+
|
|
54
|
+
addop 'i32.load', 0x28, :mem
|
|
55
|
+
addop 'i64.load', 0x29, :mem
|
|
56
|
+
addop 'f32.load', 0x2a, :mem
|
|
57
|
+
addop 'f64.load', 0x2b, :mem
|
|
58
|
+
addop 'i32.load8_s', 0x2c, :mem
|
|
59
|
+
addop 'i32.load8_u', 0x2d, :mem
|
|
60
|
+
addop 'i32.load16_s', 0x2e, :mem
|
|
61
|
+
addop 'i32.load16_u', 0x2f, :mem
|
|
62
|
+
addop 'i64.load8_s', 0x30, :mem
|
|
63
|
+
addop 'i64.load8_u', 0x31, :mem
|
|
64
|
+
addop 'i64.load16_s', 0x32, :mem
|
|
65
|
+
addop 'i64.load16_u', 0x33, :mem
|
|
66
|
+
addop 'i64.load32_s', 0x34, :mem
|
|
67
|
+
addop 'i64.load32_u', 0x35, :mem
|
|
68
|
+
addop 'i32.store', 0x36, :mem
|
|
69
|
+
addop 'i64.store', 0x37, :mem
|
|
70
|
+
addop 'f32.store', 0x38, :mem
|
|
71
|
+
addop 'f64.store', 0x39, :mem
|
|
72
|
+
addop 'i32.store8', 0x3a, :mem
|
|
73
|
+
addop 'i32.store16', 0x3b, :mem
|
|
74
|
+
addop 'i64.store8', 0x3c, :mem
|
|
75
|
+
addop 'i64.store16', 0x3d, :mem
|
|
76
|
+
addop 'i64.store32', 0x3e, :mem
|
|
77
|
+
addop 'current_memory', 0x3f, :uleb # resv1
|
|
78
|
+
addop 'grow_memory', 0x40, :uleb # resv1
|
|
79
|
+
|
|
80
|
+
addop 'i32.const', 0x41, :sleb
|
|
81
|
+
addop 'i64.const', 0x42, :sleb
|
|
82
|
+
addop 'f32.const', 0x43, :f32
|
|
83
|
+
addop 'f64.const', 0x44, :f64
|
|
84
|
+
|
|
85
|
+
addop 'i32.eqz', 0x45
|
|
86
|
+
addop 'i32.eq', 0x46
|
|
87
|
+
addop 'i32.ne', 0x47
|
|
88
|
+
addop 'i32.lt_s', 0x48
|
|
89
|
+
addop 'i32.lt_u', 0x49
|
|
90
|
+
addop 'i32.gt_s', 0x4a
|
|
91
|
+
addop 'i32.gt_u', 0x4b
|
|
92
|
+
addop 'i32.le_s', 0x4c
|
|
93
|
+
addop 'i32.le_u', 0x4d
|
|
94
|
+
addop 'i32.ge_s', 0x4e
|
|
95
|
+
addop 'i32.ge_u', 0x4f
|
|
96
|
+
addop 'i64.eqz', 0x50
|
|
97
|
+
addop 'i64.eq', 0x51
|
|
98
|
+
addop 'i64.ne', 0x52
|
|
99
|
+
addop 'i64.lt_s', 0x53
|
|
100
|
+
addop 'i64.lt_u', 0x54
|
|
101
|
+
addop 'i64.gt_s', 0x55
|
|
102
|
+
addop 'i64.gt_u', 0x56
|
|
103
|
+
addop 'i64.le_s', 0x57
|
|
104
|
+
addop 'i64.le_u', 0x58
|
|
105
|
+
addop 'i64.ge_s', 0x59
|
|
106
|
+
addop 'i64.ge_u', 0x5a
|
|
107
|
+
addop 'f32.eq', 0x5b
|
|
108
|
+
addop 'f32.ne', 0x5c
|
|
109
|
+
addop 'f32.lt', 0x5d
|
|
110
|
+
addop 'f32.gt', 0x5e
|
|
111
|
+
addop 'f32.le', 0x5f
|
|
112
|
+
addop 'f32.ge', 0x60
|
|
113
|
+
addop 'f64.eq', 0x61
|
|
114
|
+
addop 'f64.ne', 0x62
|
|
115
|
+
addop 'f64.lt', 0x63
|
|
116
|
+
addop 'f64.gt', 0x64
|
|
117
|
+
addop 'f64.le', 0x65
|
|
118
|
+
addop 'f64.ge', 0x66
|
|
119
|
+
|
|
120
|
+
addop 'i32.clz', 0x67
|
|
121
|
+
addop 'i32.ctz', 0x68
|
|
122
|
+
addop 'i32.popcnt', 0x69
|
|
123
|
+
addop 'i32.add', 0x6a
|
|
124
|
+
addop 'i32.sub', 0x6b
|
|
125
|
+
addop 'i32.mul', 0x6c
|
|
126
|
+
addop 'i32.div_s', 0x6d
|
|
127
|
+
addop 'i32.div_u', 0x6e
|
|
128
|
+
addop 'i32.rem_s', 0x6f
|
|
129
|
+
addop 'i32.rem_u', 0x70
|
|
130
|
+
addop 'i32.and', 0x71
|
|
131
|
+
addop 'i32.or', 0x72
|
|
132
|
+
addop 'i32.xor', 0x73
|
|
133
|
+
addop 'i32.shl', 0x74
|
|
134
|
+
addop 'i32.shr_s', 0x75
|
|
135
|
+
addop 'i32.shr_u', 0x76
|
|
136
|
+
addop 'i32.rotl', 0x77
|
|
137
|
+
addop 'i32.rotr', 0x78
|
|
138
|
+
addop 'i64.clz', 0x79
|
|
139
|
+
addop 'i64.ctz', 0x7a
|
|
140
|
+
addop 'i64.popcnt', 0x7b
|
|
141
|
+
addop 'i64.add', 0x7c
|
|
142
|
+
addop 'i64.sub', 0x7d
|
|
143
|
+
addop 'i64.mul', 0x7e
|
|
144
|
+
addop 'i64.div_s', 0x7f
|
|
145
|
+
addop 'i64.div_u', 0x80
|
|
146
|
+
addop 'i64.rem_s', 0x81
|
|
147
|
+
addop 'i64.rem_u', 0x82
|
|
148
|
+
addop 'i64.and', 0x83
|
|
149
|
+
addop 'i64.or', 0x84
|
|
150
|
+
addop 'i64.xor', 0x85
|
|
151
|
+
addop 'i64.shl', 0x86
|
|
152
|
+
addop 'i64.shr_s', 0x87
|
|
153
|
+
addop 'i64.shr_u', 0x88
|
|
154
|
+
addop 'i64.rotl', 0x89
|
|
155
|
+
addop 'i64.rotr', 0x8a
|
|
156
|
+
addop 'f32.abs', 0x8b
|
|
157
|
+
addop 'f32.neg', 0x8c
|
|
158
|
+
addop 'f32.ceil', 0x8d
|
|
159
|
+
addop 'f32.floor', 0x8e
|
|
160
|
+
addop 'f32.trunc', 0x8f
|
|
161
|
+
addop 'f32.nearest', 0x90
|
|
162
|
+
addop 'f32.sqrt', 0x91
|
|
163
|
+
addop 'f32.add', 0x92
|
|
164
|
+
addop 'f32.sub', 0x93
|
|
165
|
+
addop 'f32.mul', 0x94
|
|
166
|
+
addop 'f32.div', 0x95
|
|
167
|
+
addop 'f32.min', 0x96
|
|
168
|
+
addop 'f32.max', 0x97
|
|
169
|
+
addop 'f32.copysign', 0x98
|
|
170
|
+
addop 'f64.abs', 0x99
|
|
171
|
+
addop 'f64.neg', 0x9a
|
|
172
|
+
addop 'f64.ceil', 0x9b
|
|
173
|
+
addop 'f64.floor', 0x9c
|
|
174
|
+
addop 'f64.trunc', 0x9d
|
|
175
|
+
addop 'f64.nearest', 0x9e
|
|
176
|
+
addop 'f64.sqrt', 0x9f
|
|
177
|
+
addop 'f64.add', 0xa0
|
|
178
|
+
addop 'f64.sub', 0xa1
|
|
179
|
+
addop 'f64.mul', 0xa2
|
|
180
|
+
addop 'f64.div', 0xa3
|
|
181
|
+
addop 'f64.min', 0xa4
|
|
182
|
+
addop 'f64.max', 0xa5
|
|
183
|
+
addop 'f64.copysign', 0xa6
|
|
184
|
+
|
|
185
|
+
addop 'i32.wrap/i64', 0xa7
|
|
186
|
+
addop 'i32.trunc_s/f32', 0xa8
|
|
187
|
+
addop 'i32.trunc_u/f32', 0xa9
|
|
188
|
+
addop 'i32.trunc_s/f64', 0xaa
|
|
189
|
+
addop 'i32.trunc_u/f64', 0xab
|
|
190
|
+
addop 'i64.extend_s/i32', 0xac
|
|
191
|
+
addop 'i64.extend_u/i32', 0xad
|
|
192
|
+
addop 'i64.trunc_s/f32', 0xae
|
|
193
|
+
addop 'i64.trunc_u/f32', 0xaf
|
|
194
|
+
addop 'i64.trunc_s/f64', 0xb0
|
|
195
|
+
addop 'i64.trunc_u/f64', 0xb1
|
|
196
|
+
addop 'f32.convert_s/i32', 0xb2
|
|
197
|
+
addop 'f32.convert_u/i32', 0xb3
|
|
198
|
+
addop 'f32.convert_s/i64', 0xb4
|
|
199
|
+
addop 'f32.convert_u/i64', 0xb5
|
|
200
|
+
addop 'f32.demote/f64', 0xb6
|
|
201
|
+
addop 'f64.convert_s/i32', 0xb7
|
|
202
|
+
addop 'f64.convert_u/i32', 0xb8
|
|
203
|
+
addop 'f64.convert_s/i64', 0xb9
|
|
204
|
+
addop 'f64.convert_u/i64', 0xba
|
|
205
|
+
addop 'f64.promote/f32', 0xbb
|
|
206
|
+
|
|
207
|
+
addop 'i32.reinterpret/f32', 0xbc
|
|
208
|
+
addop 'i64.reinterpret/f64', 0xbd
|
|
209
|
+
addop 'f32.reinterpret/i32', 0xbe
|
|
210
|
+
addop 'f64.reinterpret/i64', 0xbf
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
end
|
|
214
|
+
end
|
|
@@ -32,6 +32,8 @@ class CCompiler < C::Compiler
|
|
|
32
32
|
attr_accessor :regargs
|
|
33
33
|
# stack space reserved for subfunction in ABI
|
|
34
34
|
attr_accessor :args_space
|
|
35
|
+
# ensure stack is 16byte aligned before calls
|
|
36
|
+
attr_accessor :stack_align16
|
|
35
37
|
# list of reg values that are not kept across function call
|
|
36
38
|
attr_accessor :abi_flushregs_call
|
|
37
39
|
# list of regs we can trash without restoring them
|
|
@@ -52,6 +54,7 @@ class CCompiler < C::Compiler
|
|
|
52
54
|
@bound = {}
|
|
53
55
|
@regargs = []
|
|
54
56
|
@args_space = 0
|
|
57
|
+
@stack_align16 = true
|
|
55
58
|
@abi_flushregs_call = [0, 1, 2, 6, 7, 8, 9, 10, 11]
|
|
56
59
|
@abi_trashregs = @abi_flushregs_call.dup
|
|
57
60
|
end
|
|
@@ -491,7 +494,9 @@ class CCompiler < C::Compiler
|
|
|
491
494
|
unuse l
|
|
492
495
|
l = Address.new(l.modrm.dup)
|
|
493
496
|
inuse l
|
|
494
|
-
if l.modrm.b
|
|
497
|
+
if (l.modrm.b and l.modrm.b.val == 16) or (l.modrm.i and l.modrm.i.val == 16)
|
|
498
|
+
# cannot encode [rip+reg+imm]
|
|
499
|
+
elsif l.modrm.b
|
|
495
500
|
if not l.modrm.i or (l.modrm.i.val == r.val and l.modrm.s == 1)
|
|
496
501
|
l.modrm.i = r
|
|
497
502
|
l.modrm.s = (l.modrm.s || 0) + 1
|
|
@@ -646,15 +651,15 @@ class CCompiler < C::Compiler
|
|
|
646
651
|
|
|
647
652
|
stackargs = expr.rexpr.zip(regargsmask).map { |a, r| a if not r }.compact
|
|
648
653
|
|
|
649
|
-
|
|
650
|
-
stackalign = true if @state.args_space > 0 and (stackargs + backup).length & 1 == 1
|
|
654
|
+
stackalign = true if @state.stack_align16 and (stackargs + backup).length & 1 == 1
|
|
651
655
|
instr 'sub', Reg.new(4, @cpusz), Expression[8] if stackalign
|
|
652
656
|
|
|
653
657
|
stackargs.reverse_each { |arg|
|
|
654
658
|
raise 'arg unhandled' if not arg.type.integral? or arg.type.pointer?
|
|
655
659
|
a = c_cexpr_inner(arg)
|
|
656
|
-
a = resolve_address a if a.kind_of?
|
|
657
|
-
a = make_volatile(a, arg.type) if a.kind_of?
|
|
660
|
+
a = resolve_address a if a.kind_of?(Address)
|
|
661
|
+
a = make_volatile(a, arg.type) if (a.kind_of?(ModRM) and arg.type.name != :__int64) or
|
|
662
|
+
(a.kind_of?(Expression) and (va = a.reduce) and (not va.kind_of?(::Integer) or va < -0x8000_0000 or va > 0x7fff_ffff))
|
|
658
663
|
unuse a
|
|
659
664
|
instr 'push', a
|
|
660
665
|
}
|
|
@@ -982,8 +987,7 @@ class CCompiler < C::Compiler
|
|
|
982
987
|
@state.dirty -= @state.abi_trashregs
|
|
983
988
|
if localspc
|
|
984
989
|
localspc = (localspc + 7) / 8 * 8
|
|
985
|
-
if @state.
|
|
986
|
-
# ensure 16-o stack align on windows
|
|
990
|
+
if @state.stack_align16 and (localspc/8 + @state.dirty.length) & 1 == 1
|
|
987
991
|
localspc += 8
|
|
988
992
|
end
|
|
989
993
|
ebp = @state.saved_rbp
|
|
@@ -1002,7 +1006,7 @@ class CCompiler < C::Compiler
|
|
|
1002
1006
|
v = findvar(a)
|
|
1003
1007
|
instr 'mov', v, Reg.new(r, v.sz)
|
|
1004
1008
|
}
|
|
1005
|
-
elsif @state.
|
|
1009
|
+
elsif @state.stack_align16 and @state.dirty.length & 1 == 0
|
|
1006
1010
|
instr 'sub', Reg.new(4, @cpusz), Expression[8]
|
|
1007
1011
|
end
|
|
1008
1012
|
@state.dirty.each { |reg|
|
|
@@ -1018,7 +1022,7 @@ class CCompiler < C::Compiler
|
|
|
1018
1022
|
if ebp = @state.saved_rbp
|
|
1019
1023
|
instr 'mov', Reg.new(4, ebp.sz), ebp
|
|
1020
1024
|
instr 'pop', ebp
|
|
1021
|
-
elsif @state.
|
|
1025
|
+
elsif @state.stack_align16 and @state.dirty.length & 1 == 0
|
|
1022
1026
|
instr 'add', Reg.new(4, @cpusz), Expression[8]
|
|
1023
1027
|
end
|
|
1024
1028
|
instr 'ret'
|