metasm 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +3 -0
  3. data.tar.gz.sig +0 -0
  4. data/Gemfile +3 -2
  5. data/metasm.gemspec +3 -2
  6. data/metasm.rb +4 -1
  7. data/metasm/compile_c.rb +2 -2
  8. data/metasm/cpu/arc/decode.rb +0 -21
  9. data/metasm/cpu/arc/main.rb +4 -4
  10. data/metasm/cpu/arm/decode.rb +1 -5
  11. data/metasm/cpu/arm/main.rb +3 -3
  12. data/metasm/cpu/arm64/decode.rb +2 -6
  13. data/metasm/cpu/arm64/main.rb +5 -5
  14. data/metasm/cpu/bpf/decode.rb +3 -35
  15. data/metasm/cpu/bpf/main.rb +5 -5
  16. data/metasm/cpu/bpf/render.rb +1 -12
  17. data/metasm/cpu/cy16/decode.rb +0 -6
  18. data/metasm/cpu/cy16/main.rb +3 -3
  19. data/metasm/cpu/cy16/render.rb +0 -11
  20. data/metasm/cpu/dalvik/decode.rb +4 -26
  21. data/metasm/cpu/dalvik/main.rb +20 -2
  22. data/metasm/cpu/dalvik/opcodes.rb +3 -2
  23. data/metasm/cpu/{mips/compile_c.rb → ebpf.rb} +5 -2
  24. data/metasm/cpu/ebpf/debug.rb +61 -0
  25. data/metasm/cpu/ebpf/decode.rb +142 -0
  26. data/metasm/cpu/ebpf/main.rb +58 -0
  27. data/metasm/cpu/ebpf/opcodes.rb +97 -0
  28. data/metasm/cpu/ebpf/render.rb +36 -0
  29. data/metasm/cpu/ia32/debug.rb +39 -1
  30. data/metasm/cpu/ia32/decode.rb +111 -90
  31. data/metasm/cpu/ia32/decompile.rb +45 -37
  32. data/metasm/cpu/ia32/main.rb +10 -0
  33. data/metasm/cpu/ia32/parse.rb +6 -0
  34. data/metasm/cpu/mcs51/decode.rb +1 -1
  35. data/metasm/cpu/mcs51/main.rb +11 -0
  36. data/metasm/cpu/mips/decode.rb +8 -18
  37. data/metasm/cpu/mips/main.rb +3 -3
  38. data/metasm/cpu/mips/opcodes.rb +1 -1
  39. data/metasm/cpu/msp430/decode.rb +2 -6
  40. data/metasm/cpu/msp430/main.rb +3 -3
  41. data/metasm/cpu/openrisc.rb +11 -0
  42. data/metasm/cpu/openrisc/debug.rb +106 -0
  43. data/metasm/cpu/openrisc/decode.rb +182 -0
  44. data/metasm/cpu/openrisc/decompile.rb +350 -0
  45. data/metasm/cpu/openrisc/main.rb +70 -0
  46. data/metasm/cpu/openrisc/opcodes.rb +109 -0
  47. data/metasm/cpu/openrisc/render.rb +37 -0
  48. data/metasm/cpu/ppc/decode.rb +0 -25
  49. data/metasm/cpu/ppc/main.rb +6 -6
  50. data/metasm/cpu/ppc/opcodes.rb +3 -4
  51. data/metasm/cpu/python/decode.rb +0 -20
  52. data/metasm/cpu/python/main.rb +1 -1
  53. data/metasm/cpu/sh4/decode.rb +2 -6
  54. data/metasm/cpu/sh4/main.rb +25 -23
  55. data/metasm/cpu/st20/decode.rb +0 -7
  56. data/metasm/cpu/webasm.rb +11 -0
  57. data/metasm/cpu/webasm/debug.rb +31 -0
  58. data/metasm/cpu/webasm/decode.rb +321 -0
  59. data/metasm/cpu/webasm/decompile.rb +386 -0
  60. data/metasm/cpu/webasm/encode.rb +104 -0
  61. data/metasm/cpu/webasm/main.rb +81 -0
  62. data/metasm/cpu/webasm/opcodes.rb +214 -0
  63. data/metasm/cpu/x86_64/compile_c.rb +13 -9
  64. data/metasm/cpu/x86_64/parse.rb +1 -1
  65. data/metasm/cpu/z80/decode.rb +0 -27
  66. data/metasm/cpu/z80/main.rb +3 -3
  67. data/metasm/cpu/z80/render.rb +0 -11
  68. data/metasm/debug.rb +43 -8
  69. data/metasm/decode.rb +62 -14
  70. data/metasm/decompile.rb +793 -466
  71. data/metasm/disassemble.rb +188 -131
  72. data/metasm/disassemble_api.rb +30 -17
  73. data/metasm/dynldr.rb +2 -2
  74. data/metasm/encode.rb +8 -2
  75. data/metasm/exe_format/autoexe.rb +2 -0
  76. data/metasm/exe_format/coff.rb +21 -3
  77. data/metasm/exe_format/coff_decode.rb +12 -0
  78. data/metasm/exe_format/coff_encode.rb +6 -3
  79. data/metasm/exe_format/dex.rb +13 -3
  80. data/metasm/exe_format/elf.rb +12 -2
  81. data/metasm/exe_format/elf_decode.rb +59 -1
  82. data/metasm/exe_format/main.rb +2 -0
  83. data/metasm/exe_format/mz.rb +1 -0
  84. data/metasm/exe_format/pe.rb +25 -3
  85. data/metasm/exe_format/wasm.rb +402 -0
  86. data/metasm/gui/dasm_decomp.rb +171 -95
  87. data/metasm/gui/dasm_graph.rb +61 -2
  88. data/metasm/gui/dasm_hex.rb +2 -2
  89. data/metasm/gui/dasm_main.rb +45 -19
  90. data/metasm/gui/debug.rb +13 -4
  91. data/metasm/gui/gtk.rb +12 -4
  92. data/metasm/main.rb +108 -103
  93. data/metasm/os/emulator.rb +175 -0
  94. data/metasm/os/main.rb +11 -6
  95. data/metasm/parse.rb +23 -12
  96. data/metasm/parse_c.rb +189 -135
  97. data/metasm/preprocessor.rb +16 -1
  98. data/misc/openrisc-parser.rb +79 -0
  99. data/samples/dasm-plugins/scanxrefs.rb +6 -4
  100. data/samples/dasm-plugins/selfmodify.rb +8 -8
  101. data/samples/dbg-plugins/trace_func.rb +1 -1
  102. data/samples/disassemble-gui.rb +14 -3
  103. data/samples/emubios.rb +251 -0
  104. data/samples/emudbg.rb +127 -0
  105. data/samples/lindebug.rb +79 -78
  106. data/samples/metasm-shell.rb +8 -8
  107. data/tests/all.rb +1 -1
  108. data/tests/expression.rb +2 -0
  109. data/tests/graph_layout.rb +1 -1
  110. data/tests/ia32.rb +1 -0
  111. data/tests/mips.rb +1 -1
  112. data/tests/preprocessor.rb +18 -0
  113. metadata +124 -6
  114. 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
- # preserve 16byte stack align under windows
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? Address
657
- a = make_volatile(a, arg.type) if a.kind_of? ModRM and arg.type.name != :__int64
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.args_space > 0 and (localspc/8 + @state.dirty.length) & 1 == 1
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.args_space > 0 and @state.dirty.length & 1 == 0
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.args_space > 0 and @state.dirty.length & 1 == 0
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'