node/lib/metasm/metasm/decompile.rb
# decompile a function, decompiling subfunctions as needed
# may return :restart, which means that the decompilation should restart from the entrypoint (and bubble up) (eg a new codepath is found which may changes dependency in blocks etc)
decompile a function, decompiling subfunctions as needed
may return :restart, which means that the decompilation should restart from the entrypoint (and bubble up)
decompile a function decompiling subfunctions as needed may return : restart which means that the decompilation should restart from the entrypoint ( and bubble up )
def decompile_func(entry)
		return if @recurse < 0
		entry = @dasm.normalize entry
		return if not @dasm.decoded[entry]
		func = C::Variable.new
		func.name = @dasm.auto_label_at(entry, 'func')
		if f = @dasm.function[entry] and f.decompdata and f.decompdata[:return_type]
			rettype = f.decompdata[:return_type]
		else
			rettype = C::BaseType.new(:int)
		end
		func.type = C::Function.new rettype, []
		if @c_parser.toplevel.symbol[func.name]
			return if @recurse == 0
			if not @c_parser.toplevel.statements.grep(C::Declaration).find { |decl| decl.var.name == func.name }
				puts "function #{func.name} is recursive: predecompiling for prototype" if $VERBOSE
				pre_recurse = @recurse
				@recurse = 0
				@c_parser.toplevel.symbol.delete func.name
				decompile_func(entry)
				@recurse = pre_recurse
				if not @c_parser.toplevel.statements.grep(C::Declaration).find { |decl| decl.var.name == func.name }
					@c_parser.toplevel.statements << C::Declaration.new(func)
				end
			end
			return
		end
		@c_parser.toplevel.symbol[func.name] = func
		puts "decompiling #{func.name}" if $VERBOSE
		while catch(:restart) { do_decompile_func(entry, func) } == :restart
			retval = :restart
		end
		@c_parser.toplevel.symbol[func.name] = func	
		@c_parser.toplevel.statements << C::Declaration.new(func)
		puts " decompiled #{func.name}" if $VERBOSE
		retval
	end
def decompile_func ( entry ) return if @recurse < 0 entry = @dasm . normalize entry return if not @dasm . decoded [ entry ] func = C :: Variable . new func . name = @dasm . auto_label_at ( entry , 'func' ) if f = @dasm . function [ entry ] and f . decompdata and f . decompdata [ :return_type ] rettype = f . decompdata [ :return_type ] else rettype = C :: BaseType . new ( :int ) end func . type = C :: Function . new rettype , [ ] if @c_parser . toplevel . symbol [ func . name ] return if @recurse == 0 if not @c_parser . toplevel . statements . grep ( C :: Declaration ) . find { | decl | decl . var . name == func . name } puts "function #{func.name} is recursive: predecompiling for prototype" if $VERBOSE pre_recurse = @recurse @recurse = 0 @c_parser . toplevel . symbol . delete func . name decompile_func ( entry ) @recurse = pre_recurse if not @c_parser . toplevel . statements . grep ( C :: Declaration ) . find { | decl | decl . var . name == func . name } @c_parser . toplevel . statements << C :: Declaration . new ( func ) end end return end @c_parser . toplevel . symbol [ func . name ] = func puts "decompiling #{func.name}" if $VERBOSE while catch ( :restart ) { do_decompile_func ( entry , func ) } == :restart retval = :restart end @c_parser . toplevel . symbol [ func . name ] = func @c_parser . toplevel . statements << C :: Declaration . new ( func ) puts " decompiled #{func.name}" if $VERBOSE retval end
decompile a function, decompiling subfunctions as needed
may return :restart, which means that the decompilation should restart from the entrypoint (and bubble up) (eg a new codepath is found which may changes dependency in blocks etc)
decompile a function decompiling subfunctions as needed may return : restart which means that the decompilation should restart from the entrypoint ( and bubble up ) ( eg a new codepath is found which may changes dependency in blocks etc )
# create a new toplevel function to hold our code # recursive dependency: declare prototype # recursive func prototype could have overwritten us
entry