metasm/cpu/x86_64/compile_c.rb in metasm-1.0.3 vs metasm/cpu/x86_64/compile_c.rb in metasm-1.0.4

- old
+ new

@@ -30,10 +30,12 @@ attr_accessor :bound # list of reg values that are used as func args in current ABI attr_accessor :regargs # stack space reserved for subfunction in ABI attr_accessor :args_space + # ensure stack is 16byte aligned before calls + attr_accessor :stack_align16 # list of reg values that are not kept across function call attr_accessor :abi_flushregs_call # list of regs we can trash without restoring them attr_accessor :abi_trashregs @@ -50,10 +52,11 @@ @used = [4] # rsp is always in use @inuse = [] @bound = {} @regargs = [] @args_space = 0 + @stack_align16 = true @abi_flushregs_call = [0, 1, 2, 6, 7, 8, 9, 10, 11] @abi_trashregs = @abi_flushregs_call.dup end end @@ -489,11 +492,13 @@ case r when Reg unuse l l = Address.new(l.modrm.dup) inuse l - if l.modrm.b + if (l.modrm.b and l.modrm.b.val == 16) or (l.modrm.i and l.modrm.i.val == 16) + # cannot encode [rip+reg+imm] + elsif l.modrm.b if not l.modrm.i or (l.modrm.i.val == r.val and l.modrm.s == 1) l.modrm.i = r l.modrm.s = (l.modrm.s || 0) + 1 unuse r return l @@ -644,19 +649,19 @@ @state.used.delete reg } stackargs = expr.rexpr.zip(regargsmask).map { |a, r| a if not r }.compact - # preserve 16byte stack align under windows - stackalign = true if @state.args_space > 0 and (stackargs + backup).length & 1 == 1 + stackalign = true if @state.stack_align16 and (stackargs + backup).length & 1 == 1 instr 'sub', Reg.new(4, @cpusz), Expression[8] if stackalign stackargs.reverse_each { |arg| raise 'arg unhandled' if not arg.type.integral? or arg.type.pointer? a = c_cexpr_inner(arg) - a = resolve_address a if a.kind_of? Address - a = make_volatile(a, arg.type) if a.kind_of? ModRM and arg.type.name != :__int64 + a = resolve_address a if a.kind_of?(Address) + a = make_volatile(a, arg.type) if (a.kind_of?(ModRM) and arg.type.name != :__int64) or + (a.kind_of?(Expression) and (va = a.reduce) and (not va.kind_of?(::Integer) or va < -0x8000_0000 or va > 0x7fff_ffff)) unuse a instr 'push', a } regargs_unuse = [] @@ -980,12 +985,11 @@ localspc = @state.offset.values.grep(::Integer).max return if @state.func.attributes.to_a.include? 'naked' @state.dirty -= @state.abi_trashregs if localspc localspc = (localspc + 7) / 8 * 8 - if @state.args_space > 0 and (localspc/8 + @state.dirty.length) & 1 == 1 - # ensure 16-o stack align on windows + if @state.stack_align16 and (localspc/8 + @state.dirty.length) & 1 == 1 localspc += 8 end ebp = @state.saved_rbp esp = Reg.new(4, ebp.sz) instr 'push', ebp @@ -1000,11 +1004,11 @@ else next end v = findvar(a) instr 'mov', v, Reg.new(r, v.sz) } - elsif @state.args_space > 0 and @state.dirty.length & 1 == 0 + elsif @state.stack_align16 and @state.dirty.length & 1 == 0 instr 'sub', Reg.new(4, @cpusz), Expression[8] end @state.dirty.each { |reg| instr 'push', Reg.new(reg, @cpusz) } @@ -1016,10 +1020,10 @@ instr 'pop', Reg.new(reg, @cpusz) } if ebp = @state.saved_rbp instr 'mov', Reg.new(4, ebp.sz), ebp instr 'pop', ebp - elsif @state.args_space > 0 and @state.dirty.length & 1 == 0 + elsif @state.stack_align16 and @state.dirty.length & 1 == 0 instr 'add', Reg.new(4, @cpusz), Expression[8] end instr 'ret' end