node/lib/metasm/metasm/cpu/ia32/decode.rb
def decode_c_function_prototype(cp, sym, orig=nil)
		sym = cp.toplevel.symbol[sym] if sym.kind_of?(::String)
		df = DecodedFunction.new
		orig ||= Expression[sym.name]

		new_bt = lambda { |expr, rlen|
			df.backtracked_for << BacktraceTrace.new(expr, orig, expr, rlen ? :r : :x, rlen)
		}

		# return instr emulation
		if sym.has_attribute 'noreturn' or sym.has_attribute '__noreturn__'
			df.noreturn = true
		else
			new_bt[Indirection[:esp, @size/8, orig], nil]
		end

		# register dirty (XXX assume standard ABI)
		[:eax, :ecx, :edx].each { |r|
			df.backtrace_binding.update r => Expression::Unknown
		}

		# emulate ret <n>
		al = cp.typesize[:ptr]
		stackoff = al
		if sym.has_attribute 'fastcall'
			stackoff = sym.type.args.to_a[2..-1].to_a.inject(al) { |sum, a| sum += (cp.sizeof(a) + al - 1) / al * al }
		elsif sym.has_attribute 'stdcall'
			stackoff = sym.type.args.to_a.inject(al) { |sum, a| sum += (cp.sizeof(a) + al - 1) / al * al }
		end
		df.backtrace_binding[:esp] = Expression[:esp, :+, stackoff]

		# scan args for function pointers
		# TODO walk structs/unions..
		stackoff = al
		sym.type.args.to_a.each { |a|
			p = Indirection[[:esp, :+, stackoff], al, orig]
			stackoff += (cp.sizeof(a) + al - 1) / al * al
			if a.type.untypedef.kind_of? C::Pointer
				pt = a.type.untypedef.type.untypedef
				if pt.kind_of? C::Function
					new_bt[p, nil]
					df.backtracked_for.last.detached = true
				elsif pt.kind_of? C::Struct
					new_bt[p, al]
				else
					new_bt[p, cp.sizeof(nil, pt)]
				end
			end
		}

		df
	end
# returns a DecodedFunction from a parsed C function prototype
# TODO rebacktrace already decoded functions (load a header file after dasm finished)
# TODO walk structs args
returns a DecodedFunction from a parsed C function prototype
TODO rebacktrace already decoded functions (load a header file after dasm finished)
TODO walk structs args
returns a DecodedFunction from a parsed C function prototype TODO rebacktrace already decoded functions ( load a header file after dasm finished ) TODO walk structs args
def decode_c_function_prototype(cp, sym, orig=nil)
		sym = cp.toplevel.symbol[sym] if sym.kind_of?(::String)
		df = DecodedFunction.new
		orig ||= Expression[sym.name]
		new_bt = lambda { |expr, rlen|
			df.backtracked_for << BacktraceTrace.new(expr, orig, expr, rlen ? :r : :x, rlen)
		}
		if sym.has_attribute 'noreturn' or sym.has_attribute '__noreturn__'
			df.noreturn = true
		else
			new_bt[Indirection[:esp, @size/8, orig], nil]
		end
		[:eax, :ecx, :edx].each { |r|
			df.backtrace_binding.update r => Expression::Unknown
		}
		al = cp.typesize[:ptr]
		stackoff = al
		if sym.has_attribute 'fastcall'
			stackoff = sym.type.args.to_a[2..-1].to_a.inject(al) { |sum, a| sum += (cp.sizeof(a) + al - 1) / al * al }
		elsif sym.has_attribute 'stdcall'
			stackoff = sym.type.args.to_a.inject(al) { |sum, a| sum += (cp.sizeof(a) + al - 1) / al * al }
		end
		df.backtrace_binding[:esp] = Expression[:esp, :+, stackoff]
		stackoff = al
		sym.type.args.to_a.each { |a|
			p = Indirection[[:esp, :+, stackoff], al, orig]
			stackoff += (cp.sizeof(a) + al - 1) / al * al
			if a.type.untypedef.kind_of? C::Pointer
				pt = a.type.untypedef.type.untypedef
				if pt.kind_of? C::Function
					new_bt[p, nil]
					df.backtracked_for.last.detached = true
				elsif pt.kind_of? C::Struct
					new_bt[p, al]
				else
					new_bt[p, cp.sizeof(nil, pt)]
				end
			end
		}
		df
	end
def decode_c_function_prototype ( cp , sym , orig = nil ) sym = cp . toplevel . symbol [ sym ] if sym . kind_of? ( :: String ) df = DecodedFunction . new orig ||= Expression [ sym . name ] new_bt = lambda { | expr , rlen | df . backtracked_for << BacktraceTrace . new ( expr , orig , expr , rlen ? :r : :x , rlen ) } if sym . has_attribute 'noreturn' or sym . has_attribute '__noreturn__' df . noreturn = true else new_bt [ Indirection [ :esp , @size / 8 , orig ] , nil ] end [ :eax , :ecx , :edx ] . each { | r | df . backtrace_binding . update r => Expression :: Unknown } al = cp . typesize [ :ptr ] stackoff = al if sym . has_attribute 'fastcall' stackoff = sym . type . args . to_a [ 2 .. - 1 ] . to_a . inject ( al ) { | sum , a | sum += ( cp . sizeof ( a ) + al - 1 ) / al * al } elsif sym . has_attribute 'stdcall' stackoff = sym . type . args . to_a . inject ( al ) { | sum , a | sum += ( cp . sizeof ( a ) + al - 1 ) / al * al } end df . backtrace_binding [ :esp ] = Expression [ :esp , :+ , stackoff ] stackoff = al sym . type . args . to_a . each { | a | p = Indirection [ [ :esp , :+ , stackoff ] , al , orig ] stackoff += ( cp . sizeof ( a ) + al - 1 ) / al * al if a . type . untypedef . kind_of? C :: Pointer pt = a . type . untypedef . type . untypedef if pt . kind_of? C :: Function new_bt [ p , nil ] df . backtracked_for . last . detached = true elsif pt . kind_of? C :: Struct new_bt [ p , al ] else new_bt [ p , cp . sizeof ( nil , pt ) ] end end } df end
returns a DecodedFunction from a parsed C function prototype
TODO rebacktrace already decoded functions (load a header file after dasm finished)
TODO walk structs args
returns a DecodedFunction from a parsed C function prototype TODO rebacktrace already decoded functions ( load a header file after dasm finished ) TODO walk structs args
# return instr emulation # register dirty (XXX assume standard ABI) # emulate ret <n> # scan args for function pointers # TODO walk structs/unions..
cp
sym
orig