node/lib/metasm/metasm/cpu/ia32/decompile.rb
# temporarily setup dasm.address_binding so that backtracking
# stack-related offsets resolve in :frameptr (relative to func start)
temporarily setup dasm.address_binding so that backtracking
stack-related offsets resolve in :frameptr (relative to func start)
temporarily setup dasm . address_binding so that backtracking stack - related offsets resolve in : frameptr ( relative to func start )
def decompile_check_abi(dcmp, entry, func)
		a = func.type.args || []
		a.delete_if { |arg| arg.has_attribute_var('register') and arg.has_attribute('unused') }
		ra =  a.map { |arg| arg.has_attribute_var('register') }.compact
		if (a.length == 1 and ra == ['ecx']) or (a.length >= 2 and ra.sort == ['ecx', 'edx'])
			func.add_attribute 'fastcall'
			ecx = a.find { |arg| arg.has_attribute_var('register') == 'ecx' }
			edx = a.find { |arg| arg.has_attribute_var('register') == 'edx' }
			a.insert(0, a.delete(ecx))
			a.insert(1, a.delete(edx)) if edx
		end
		if not f = dcmp.dasm.function[entry] or not f.return_address
		else
			adj = f.return_address.map { |ra_| dcmp.dasm.backtrace(:esp, ra_, :include_start => true, :stopaddr => entry) }.flatten.uniq
			if adj.length == 1 and so = Expression[adj.first, :-, :esp].reduce and so.kind_of? ::Integer
				argsz = a.map { |fa|
					next if not fa.stackoff
					(fa.stackoff + [dcmp.sizeof(fa), dcmp.c_parser.typesize[:ptr]].max-1) / dcmp.c_parser.typesize[:ptr]
				}.compact.max.to_i
				so /= dcmp.dasm.cpu.size/8
				so -= 1
				if so > argsz
					aso = a.empty? ? 0 : a.last.stackoff.to_i + dcmp.c_parser.typesize[:ptr]
					(so-argsz).times {
						a << C::Variable.new(dcmp.stackoff_to_varname(aso), C::BaseType.new(:int))
						a.last.add_attribute('unused')
						aso += dcmp.sizeof(a.last)
					}
					argsz = so
				end
				case so
				when 0
				when argsz
					func.add_attribute 'stdcall' if not func.has_attribute('fastcall')
				else
					func.add_attribute "stackoff:#{so*dcmp.dasm.cpu.size/8}"
				end
			else
				func.add_attribute "breakstack:#{adj.inspect}"
			end
		end
	end
def decompile_check_abi ( dcmp , entry , func ) a = func . type . args || [ ] a . delete_if { | arg | arg . has_attribute_var ( 'register' ) and arg . has_attribute ( 'unused' ) } ra = a . map { | arg | arg . has_attribute_var ( 'register' ) } . compact if ( a . length == 1 and ra == [ 'ecx' ] ) or ( a . length >= 2 and ra . sort == [ 'ecx' , 'edx' ] ) func . add_attribute 'fastcall' ecx = a . find { | arg | arg . has_attribute_var ( 'register' ) == 'ecx' } edx = a . find { | arg | arg . has_attribute_var ( 'register' ) == 'edx' } a . insert ( 0 , a . delete ( ecx ) ) a . insert ( 1 , a . delete ( edx ) ) if edx end if not f = dcmp . dasm . function [ entry ] or not f . return_address else adj = f . return_address . map { | ra_ | dcmp . dasm . backtrace ( :esp , ra_ , :include_start => true , :stopaddr => entry ) } . flatten . uniq if adj . length == 1 and so = Expression [ adj . first , :- , :esp ] . reduce and so . kind_of? :: Integer argsz = a . map { | fa | next if not fa . stackoff ( fa . stackoff + [ dcmp . sizeof ( fa ) , dcmp . c_parser . typesize [ :ptr ] ] . max - 1 ) / dcmp . c_parser . typesize [ :ptr ] } . compact . max . to_i so /= dcmp . dasm . cpu . size / 8 so -= 1 if so > argsz aso = a . empty? ? 0 : a . last . stackoff . to_i + dcmp . c_parser . typesize [ :ptr ] ( so - argsz ) . times { a << C :: Variable . new ( dcmp . stackoff_to_varname ( aso ) , C :: BaseType . new ( :int ) ) a . last . add_attribute ( 'unused' ) aso += dcmp . sizeof ( a . last ) } argsz = so end case so when 0 when argsz func . add_attribute 'stdcall' if not func . has_attribute ( 'fastcall' ) else func . add_attribute "stackoff:#{so*dcmp.dasm.cpu.size/8}" end else func . add_attribute "breakstack:#{adj.inspect}" end end end
temporarily setup dasm.address_binding so that backtracking
stack-related offsets resolve in :frameptr (relative to func start)
temporarily setup dasm . address_binding so that backtracking stack - related offsets resolve in : frameptr ( relative to func start )
# reorder args #func.add_attribute 'noreturn'
dcmp
entry
func