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