node/lib/metasm/metasm/disassemble.rb
# disassembles fast a new instruction block at block.address (must be normalized)
# does not recurse into subfunctions
# assumes all :saveip returns, except those pointing to a subfunc with noreturn
# yields subfunction addresses (targets of :saveip)
# no backtrace for :x (change with backtrace_maxblocks_fast)
# returns a todo-style ary
# assumes @addrs_todo is empty
disassembles fast a new instruction block at block.address (must be normalized)
does not recurse into subfunctions
assumes all :saveip returns, except those pointing to a subfunc with noreturn
yields subfunction addresses (targets of :saveip)
no backtrace for :x (change with backtrace_maxblocks_fast)
returns a todo-style ary
assumes @addrs_todo is empty
disassembles fast a new instruction block at block . address ( must be normalized ) does not recurse into subfunctions assumes all : saveip returns except those pointing to a subfunc with noreturn yields subfunction addresses ( targets of : saveip ) no backtrace for : x ( change with backtrace_maxblocks_fast ) returns a todo - style ary assumes @addrs_todo is empty
def disassemble_fast_block(block, &b)
		block = InstructionBlock.new(normalize(block), get_section_at(block)[0]) if not block.kind_of? InstructionBlock
		di_addr = block.address
		delay_slot = nil
		di = nil
		ret = []
		return ret if @decoded[di_addr]
		@disassemble_maxblocklength.times {
			break if @decoded[di_addr]
			block.edata.ptr = di_addr - block.address + block.edata_ptr
			if not di = @cpu.decode_instruction(block.edata, di_addr)
				break if block.edata.ptr >= block.edata.length and get_section_at(di_addr) and di = block.list.last
				return ret
			end
			@decoded[di_addr] = di
			block.add_di di
			puts di if $DEBUG
			if callback_newinstr
				ndi = @callback_newinstr[di]
				if not ndi or not ndi.block
					block.list.delete di
					if ndi
						block.add_di ndi
						ndi.bin_length = di.bin_length if ndi.bin_length == 0
						@decoded[di_addr] = ndi
					end
				end
				di = ndi
			end
			return ret if not di
			di_addr = di.next_addr
			if di.opcode.props[:stopexec] or di.opcode.props[:setip]
				if di.opcode.props[:setip]
					@addrs_todo = []
					ar = @program.get_xrefs_x(self, di)
					ar = @callback_newaddr[di.address, ar] || ar if callback_newaddr
					ar.each { |expr|
						backtrace(expr, di.address, :origin => di.address, :type => :x, :maxdepth => @backtrace_maxblocks_fast)
					}
				end
				if di.opcode.props[:saveip]
					@addrs_todo = []
					ret.concat disassemble_fast_block_subfunc(di, &b)
				else
					ret.concat @addrs_todo
					@addrs_todo = []
				end
				delay_slot ||= [di, @cpu.delay_slot(di)]
			end
			if delay_slot
				if delay_slot[1] <= 0
					return ret if delay_slot[0].opcode.props[:stopexec]
					break
				end
				delay_slot[1] -= 1
			end
		}
		ar = [di_addr]
		ar = @callback_newaddr[block.list.last.address, ar] || ar if callback_newaddr
		ar.each { |a|
			di.block.add_to_normal(a)
			ret << [a, di.address]
		}
		ret
	end
def disassemble_fast_block ( block , & b ) block = InstructionBlock . new ( normalize ( block ) , get_section_at ( block ) [ 0 ] ) if not block . kind_of? InstructionBlock di_addr = block . address delay_slot = nil di = nil ret = [ ] return ret if @decoded [ di_addr ] @disassemble_maxblocklength . times { break if @decoded [ di_addr ] block . edata . ptr = di_addr - block . address + block . edata_ptr if not di = @cpu . decode_instruction ( block . edata , di_addr ) break if block . edata . ptr >= block . edata . length and get_section_at ( di_addr ) and di = block . list . last return ret end @decoded [ di_addr ] = di block . add_di di puts di if $DEBUG if callback_newinstr ndi = @callback_newinstr [ di ] if not ndi or not ndi . block block . list . delete di if ndi block . add_di ndi ndi . bin_length = di . bin_length if ndi . bin_length == 0 @decoded [ di_addr ] = ndi end end di = ndi end return ret if not di di_addr = di . next_addr if di . opcode . props [ :stopexec ] or di . opcode . props [ :setip ] if di . opcode . props [ :setip ] @addrs_todo = [ ] ar = @program . get_xrefs_x ( self , di ) ar = @callback_newaddr [ di . address , ar ] || ar if callback_newaddr ar . each { | expr | backtrace ( expr , di . address , :origin => di . address , :type => :x , :maxdepth => @backtrace_maxblocks_fast ) } end if di . opcode . props [ :saveip ] @addrs_todo = [ ] ret . concat disassemble_fast_block_subfunc ( di , & b ) else ret . concat @addrs_todo @addrs_todo = [ ] end delay_slot ||= [ di , @cpu . delay_slot ( di ) ] end if delay_slot if delay_slot [ 1 ] <= 0 return ret if delay_slot [ 0 ] . opcode . props [ :stopexec ] break end delay_slot [ 1 ] -= 1 end } ar = [ di_addr ] ar = @callback_newaddr [ block . list . last . address , ar ] || ar if callback_newaddr ar . each { | a | di . block . add_to_normal ( a ) ret << [ a , di . address ] } ret end
disassembles fast a new instruction block at block.address (must be normalized)
does not recurse into subfunctions
assumes all :saveip returns, except those pointing to a subfunc with noreturn
yields subfunction addresses (targets of :saveip)
no backtrace for :x (change with backtrace_maxblocks_fast)
returns a todo-style ary
assumes @addrs_todo is empty
disassembles fast a new instruction block at block . address ( must be normalized ) does not recurse into subfunctions assumes all : saveip returns except those pointing to a subfunc with noreturn yields subfunction addresses ( targets of : saveip ) no backtrace for : x ( change with backtrace_maxblocks_fast ) returns a todo - style ary assumes @addrs_todo is empty
# decode instruction
block
b