node/lib/metasm/metasm/disassemble.rb
def disassemble_step
		return if not todo = @addrs_todo.pop or @addrs_done.include? todo
		@addrs_done << todo if todo[1]

		# from_sfret is true if from is the address of a function call that returns to addr
		addr, from, from_subfuncret = todo

		return if from == Expression::Unknown

		puts "disassemble_step #{Expression[addr]} #{Expression[from] if from} #{from_subfuncret}  (/#{@addrs_todo.length})" if $DEBUG

		addr = normalize(addr)

		if from and from_subfuncret and di_at(from)
			@decoded[from].block.each_to_normal { |subfunc|
				subfunc = normalize(subfunc)
				next if not f = @function[subfunc] or f.finalized
				f.finalized = true
puts "  finalize subfunc #{Expression[subfunc]}" if debug_backtrace
				backtrace_update_function_binding(subfunc, f)
				if not f.return_address
					detect_function_thunk(subfunc)
				end
			}
		end

		if di = @decoded[addr]
			if di.kind_of? DecodedInstruction
				split_block(di.block, di.address, true) if not di.block_head?	# this updates di.block
				di.block.add_from(from, from_subfuncret ? :subfuncret : :normal) if from and from != :default
				bf = di.block
			elsif di == true
				bf = @function[addr]
			end
		elsif bf = @function[addr]
			detect_function_thunk_noreturn(from) if bf.noreturn
		elsif s = get_section_at(addr)
			block = InstructionBlock.new(normalize(addr), s[0])
			block.add_from(from, from_subfuncret ? :subfuncret : :normal) if from and from != :default
			disassemble_block(block)
		elsif from and c_parser and name = Expression[addr].reduce_rec and name.kind_of? ::String and
				s = c_parser.toplevel.symbol[name] and s.type.untypedef.kind_of? C::Function
			bf = @function[addr] = @cpu.decode_c_function_prototype(@c_parser, s)
			detect_function_thunk_noreturn(from) if bf.noreturn
		elsif from
			if bf = @function[:default]
				puts "using default function for #{Expression[addr]} from #{Expression[from]}" if $DEBUG
				if name = Expression[addr].reduce_rec and name.kind_of? ::String
					@function[addr] = @function[:default].dup
				else
					addr = :default
				end
				if @decoded[from]
					@decoded[from].block.add_to addr
				end
			else
				puts "not disassembling unknown address #{Expression[addr]} from #{Expression[from]}" if $DEBUG
			end
			if from != :default
				add_xref(addr, Xref.new(:x, from))
				add_xref(Expression::Unknown, Xref.new(:x, from))
			end
		else
			puts "not disassembling unknown address #{Expression[addr]}" if $VERBOSE
		end

		if bf and from and from != :default
			if bf.kind_of? DecodedFunction
				bff = bf.get_backtracked_for(self, addr, from)
			else
				bff = bf.backtracked_for
			end
		end
		bff.each { |btt|
			next if btt.address
			if @decoded[from].kind_of? DecodedInstruction and @decoded[from].opcode.props[:saveip] and not from_subfuncret and not @function[addr]
				backtrace_check_found(btt.expr, @decoded[addr], btt.origin, btt.type, btt.len, btt.maxdepth, btt.detached)
			end
			next if backtrace_check_funcret(btt, addr, from)
			backtrace(btt.expr, from,
				  :include_start => true, :from_subfuncret => from_subfuncret,
				  :origin => btt.origin, :orig_expr => btt.orig_expr, :type => btt.type,
				  :len => btt.len, :detached => btt.detached, :maxdepth => btt.maxdepth)
		} if bff
	end
# disassembles one block from addrs_todo
# adds next addresses to handle to addrs_todo
# if @function[:default] exists, jumps to unknows locations are interpreted as to @function[:default]
disassembles one block from addrs_todo
adds next addresses to handle to addrs_todo
if @function[:default] exists, jumps to unknows locations are interpreted as to @function[:default]
disassembles one block from addrs_todo adds next addresses to handle to addrs_todo if @function [ : default ] exists jumps to unknows locations are interpreted as to @function [ : default ]
def disassemble_step
		return if not todo = @addrs_todo.pop or @addrs_done.include? todo
		@addrs_done << todo if todo[1]
		addr, from, from_subfuncret = todo
		return if from == Expression::Unknown
		puts "disassemble_step #{Expression[addr]} #{Expression[from] if from} #{from_subfuncret}  (/#{@addrs_todo.length})" if $DEBUG
		addr = normalize(addr)
		if from and from_subfuncret and di_at(from)
			@decoded[from].block.each_to_normal { |subfunc|
				subfunc = normalize(subfunc)
				next if not f = @function[subfunc] or f.finalized
				f.finalized = true
puts "  finalize subfunc #{Expression[subfunc]}" if debug_backtrace
				backtrace_update_function_binding(subfunc, f)
				if not f.return_address
					detect_function_thunk(subfunc)
				end
			}
		end
		if di = @decoded[addr]
			if di.kind_of? DecodedInstruction
				split_block(di.block, di.address, true) if not di.block_head?	
				di.block.add_from(from, from_subfuncret ? :subfuncret : :normal) if from and from != :default
				bf = di.block
			elsif di == true
				bf = @function[addr]
			end
		elsif bf = @function[addr]
			detect_function_thunk_noreturn(from) if bf.noreturn
		elsif s = get_section_at(addr)
			block = InstructionBlock.new(normalize(addr), s[0])
			block.add_from(from, from_subfuncret ? :subfuncret : :normal) if from and from != :default
			disassemble_block(block)
		elsif from and c_parser and name = Expression[addr].reduce_rec and name.kind_of? ::String and
				s = c_parser.toplevel.symbol[name] and s.type.untypedef.kind_of? C::Function
			bf = @function[addr] = @cpu.decode_c_function_prototype(@c_parser, s)
			detect_function_thunk_noreturn(from) if bf.noreturn
		elsif from
			if bf = @function[:default]
				puts "using default function for #{Expression[addr]} from #{Expression[from]}" if $DEBUG
				if name = Expression[addr].reduce_rec and name.kind_of? ::String
					@function[addr] = @function[:default].dup
				else
					addr = :default
				end
				if @decoded[from]
					@decoded[from].block.add_to addr
				end
			else
				puts "not disassembling unknown address #{Expression[addr]} from #{Expression[from]}" if $DEBUG
			end
			if from != :default
				add_xref(addr, Xref.new(:x, from))
				add_xref(Expression::Unknown, Xref.new(:x, from))
			end
		else
			puts "not disassembling unknown address #{Expression[addr]}" if $VERBOSE
		end
		if bf and from and from != :default
			if bf.kind_of? DecodedFunction
				bff = bf.get_backtracked_for(self, addr, from)
			else
				bff = bf.backtracked_for
			end
		end
		bff.each { |btt|
			next if btt.address
			if @decoded[from].kind_of? DecodedInstruction and @decoded[from].opcode.props[:saveip] and not from_subfuncret and not @function[addr]
				backtrace_check_found(btt.expr, @decoded[addr], btt.origin, btt.type, btt.len, btt.maxdepth, btt.detached)
			end
			next if backtrace_check_funcret(btt, addr, from)
			backtrace(btt.expr, from,
				  :include_start => true, :from_subfuncret => from_subfuncret,
				  :origin => btt.origin, :orig_expr => btt.orig_expr, :type => btt.type,
				  :len => btt.len, :detached => btt.detached, :maxdepth => btt.maxdepth)
		} if bff
	end
def disassemble_step return if not todo = @addrs_todo . pop or @addrs_done . include? todo @addrs_done << todo if todo [ 1 ] addr , from , from_subfuncret = todo return if from == Expression :: Unknown puts "disassemble_step #{Expression[addr]} #{Expression[from] if from} #{from_subfuncret}  (/#{@addrs_todo.length})" if $DEBUG addr = normalize ( addr ) if from and from_subfuncret and di_at ( from ) @decoded [ from ] . block . each_to_normal { | subfunc | subfunc = normalize ( subfunc ) next if not f = @function [ subfunc ] or f . finalized f . finalized = true puts "  finalize subfunc #{Expression[subfunc]}" if debug_backtrace backtrace_update_function_binding ( subfunc , f ) if not f . return_address detect_function_thunk ( subfunc ) end } end if di = @decoded [ addr ] if di . kind_of? DecodedInstruction split_block ( di . block , di . address , true ) if not di . block_head? di . block . add_from ( from , from_subfuncret ? :subfuncret : :normal ) if from and from != :default bf = di . block elsif di == true bf = @function [ addr ] end elsif bf = @function [ addr ] detect_function_thunk_noreturn ( from ) if bf . noreturn elsif s = get_section_at ( addr ) block = InstructionBlock . new ( normalize ( addr ) , s [ 0 ] ) block . add_from ( from , from_subfuncret ? :subfuncret : :normal ) if from and from != :default disassemble_block ( block ) elsif from and c_parser and name = Expression [ addr ] . reduce_rec and name . kind_of? :: String and s = c_parser . toplevel . symbol [ name ] and s . type . untypedef . kind_of? C :: Function bf = @function [ addr ] = @cpu . decode_c_function_prototype ( @c_parser , s ) detect_function_thunk_noreturn ( from ) if bf . noreturn elsif from if bf = @function [ :default ] puts "using default function for #{Expression[addr]} from #{Expression[from]}" if $DEBUG if name = Expression [ addr ] . reduce_rec and name . kind_of? :: String @function [ addr ] = @function [ :default ] . dup else addr = :default end if @decoded [ from ] @decoded [ from ] . block . add_to addr end else puts "not disassembling unknown address #{Expression[addr]} from #{Expression[from]}" if $DEBUG end if from != :default add_xref ( addr , Xref . new ( :x , from ) ) add_xref ( Expression :: Unknown , Xref . new ( :x , from ) ) end else puts "not disassembling unknown address #{Expression[addr]}" if $VERBOSE end if bf and from and from != :default if bf . kind_of? DecodedFunction bff = bf . get_backtracked_for ( self , addr , from ) else bff = bf . backtracked_for end end bff . each { | btt | next if btt . address if @decoded [ from ] . kind_of? DecodedInstruction and @decoded [ from ] . opcode . props [ :saveip ] and not from_subfuncret and not @function [ addr ] backtrace_check_found ( btt . expr , @decoded [ addr ] , btt . origin , btt . type , btt . len , btt . maxdepth , btt . detached ) end next if backtrace_check_funcret ( btt , addr , from ) backtrace ( btt . expr , from , :include_start => true , :from_subfuncret => from_subfuncret , :origin => btt . origin , :orig_expr => btt . orig_expr , :type => btt . type , :len => btt . len , :detached => btt . detached , :maxdepth => btt . maxdepth ) } if bff end
disassembles one block from addrs_todo
adds next addresses to handle to addrs_todo
if @function[:default] exists, jumps to unknows locations are interpreted as to @function[:default]
disassembles one block from addrs_todo adds next addresses to handle to addrs_todo if @function [ : default ] exists jumps to unknows locations are interpreted as to @function [ : default ]
# from_sfret is true if from is the address of a function call that returns to addr # this updates di.block