node/lib/metasm/metasm/cpu/ia32/decompile.rb
def decompile_makestackvars(dasm, funcstart, blocks)
		oldfuncbd = dasm.address_binding[funcstart]
		dasm.address_binding[funcstart] = { :esp => :frameptr }	# this would suffice, the rest here is just optimisation

		patched_binding = [funcstart]	# list of addresses to cleanup later
		ebp_frame = true

		# pretrace esp and ebp for each function block (cleared later)
		# TODO with more than 1 unknown __stdcall ext func per path, esp -> unknown, which makes very ugly C (*esp-- = 12...); add heuristics ?
		blocks.each { |block|
			blockstart = block.address
			if not dasm.address_binding[blockstart]
				patched_binding << blockstart
				dasm.address_binding[blockstart] = {}
				foo = dasm.backtrace(:esp, blockstart, :snapshot_addr => funcstart)
				if foo.length == 1 and ee = foo.first and ee.kind_of? Expression and (ee == Expression[:frameptr] or
						(ee.lexpr == :frameptr and ee.op == :+ and ee.rexpr.kind_of? ::Integer))
					dasm.address_binding[blockstart][:esp] = ee
				end
				if ebp_frame
					foo = dasm.backtrace(:ebp, blockstart, :snapshot_addr => funcstart)
					if foo.length == 1 and ee = foo.first and ee.kind_of? Expression and (ee == Expression[:frameptr] or
							(ee.lexpr == :frameptr and ee.op == :+ and ee.rexpr.kind_of? ::Integer))
						dasm.address_binding[blockstart][:ebp] = ee
					else
						ebp_frame = false	# func does not use ebp as frame ptr, no need to bt for later blocks
					end
				end
			end

			yield block
		}

	ensure
		patched_binding.each { |a| dasm.address_binding.delete a }
		dasm.address_binding[funcstart] = oldfuncbd if oldfuncbd
	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)
temporarily setup dasm . address_binding so that backtracking stack - related offsets resolve in : frameptr ( relative to func start )
def decompile_makestackvars(dasm, funcstart, blocks)
		oldfuncbd = dasm.address_binding[funcstart]
		dasm.address_binding[funcstart] = { :esp => :frameptr }	
		patched_binding = [funcstart]	
		ebp_frame = true
		blocks.each { |block|
			blockstart = block.address
			if not dasm.address_binding[blockstart]
				patched_binding << blockstart
				dasm.address_binding[blockstart] = {}
				foo = dasm.backtrace(:esp, blockstart, :snapshot_addr => funcstart)
				if foo.length == 1 and ee = foo.first and ee.kind_of? Expression and (ee == Expression[:frameptr] or
						(ee.lexpr == :frameptr and ee.op == :+ and ee.rexpr.kind_of? ::Integer))
					dasm.address_binding[blockstart][:esp] = ee
				end
				if ebp_frame
					foo = dasm.backtrace(:ebp, blockstart, :snapshot_addr => funcstart)
					if foo.length == 1 and ee = foo.first and ee.kind_of? Expression and (ee == Expression[:frameptr] or
							(ee.lexpr == :frameptr and ee.op == :+ and ee.rexpr.kind_of? ::Integer))
						dasm.address_binding[blockstart][:ebp] = ee
					else
						ebp_frame = false	
					end
				end
			end
			yield block
		}
	ensure
		patched_binding.each { |a| dasm.address_binding.delete a }
		dasm.address_binding[funcstart] = oldfuncbd if oldfuncbd
	end
def decompile_makestackvars ( dasm , funcstart , blocks ) oldfuncbd = dasm . address_binding [ funcstart ] dasm . address_binding [ funcstart ] = { :esp => :frameptr } patched_binding = [ funcstart ] ebp_frame = true blocks . each { | block | blockstart = block . address if not dasm . address_binding [ blockstart ] patched_binding << blockstart dasm . address_binding [ blockstart ] = { } foo = dasm . backtrace ( :esp , blockstart , :snapshot_addr => funcstart ) if foo . length == 1 and ee = foo . first and ee . kind_of? Expression and ( ee == Expression [ :frameptr ] or ( ee . lexpr == :frameptr and ee . op == :+ and ee . rexpr . kind_of? :: Integer ) ) dasm . address_binding [ blockstart ] [ :esp ] = ee end if ebp_frame foo = dasm . backtrace ( :ebp , blockstart , :snapshot_addr => funcstart ) if foo . length == 1 and ee = foo . first and ee . kind_of? Expression and ( ee == Expression [ :frameptr ] or ( ee . lexpr == :frameptr and ee . op == :+ and ee . rexpr . kind_of? :: Integer ) ) dasm . address_binding [ blockstart ] [ :ebp ] = ee else ebp_frame = false end end end yield block } ensure patched_binding . each { | a | dasm . address_binding . delete a } dasm . address_binding [ funcstart ] = oldfuncbd if oldfuncbd 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 )
# this would suffice, the rest here is just optimisation # list of addresses to cleanup later # pretrace esp and ebp for each function block (cleared later) # TODO with more than 1 unknown __stdcall ext func per path, esp -> unknown, which makes very ugly C (*esp-- = 12...); add heuristics ? # func does not use ebp as frame ptr, no need to bt for later blocks
dasm
funcstart
blocks