node/lib/metasm/metasm/disassemble.rb
# disassembles a new instruction block at block.address (must be normalized)
disassembles a new instruction block at block.address (must be normalized)
disassembles a new instruction block at block . address ( must be normalized )
def disassemble_block(block)
		raise if not block.list.empty?
		di_addr = block.address
		delay_slot = nil
		di = nil
		@disassemble_maxblocklength.times {
			break if @decoded[di_addr]
			if @check_smc
				waddr = di_addr		
				each_xref(waddr, :w) { |x|
					puts "W: disasm: self-modifying code at #{Expression[waddr]}" if $VERBOSE
					add_comment(di_addr, "overwritten by #{@decoded[x.origin]}")
					@callback_selfmodifying[di_addr] if callback_selfmodifying
					return
				}
			end
			block.edata.ptr = di_addr - block.address + block.edata_ptr
			if not di = @cpu.decode_instruction(block.edata, di_addr)
				ed = block.edata
				break if ed.ptr >= ed.length and get_section_at(di_addr) and di = block.list.last
				puts "#{ed.ptr >= ed.length ? "end of section reached" : "unknown instruction #{ed.data[di_addr-block.address+block.edata_ptr, 4].to_s.unpack('H*')}"} at #{Expression[di_addr]}" if $VERBOSE
				return
			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 if not di
			block = di.block
			di_addr = di.next_addr
			backtrace_xrefs_di_rw(di)
			if not di_addr or di.opcode.props[:stopexec] or not @program.get_xrefs_x(self, di).empty?
				delay_slot ||= [di, @cpu.delay_slot(di)]
			end
			if delay_slot
				di, delay = delay_slot
				if delay == 0 or not di_addr
					backtrace_xrefs_di_x(di)
					if di.opcode.props[:stopexec] or not di_addr; return
					else break
					end
				end
				delay_slot[1] = delay - 1
			end
		}
		ar = [di_addr]
		ar = @callback_newaddr[block.list.last.address, ar] || ar if callback_newaddr
		ar.each { |di_addr_| backtrace(di_addr_, di.address, :origin => di.address, :type => :x) }
		block
	end
def disassemble_block ( block ) raise if not block . list . empty? di_addr = block . address delay_slot = nil di = nil @disassemble_maxblocklength . times { break if @decoded [ di_addr ] if @check_smc waddr = di_addr each_xref ( waddr , :w ) { | x | puts "W: disasm: self-modifying code at #{Expression[waddr]}" if $VERBOSE add_comment ( di_addr , "overwritten by #{@decoded[x.origin]}" ) @callback_selfmodifying [ di_addr ] if callback_selfmodifying return } end block . edata . ptr = di_addr - block . address + block . edata_ptr if not di = @cpu . decode_instruction ( block . edata , di_addr ) ed = block . edata break if ed . ptr >= ed . length and get_section_at ( di_addr ) and di = block . list . last puts "#{ed.ptr >= ed.length ? "end of section reached" : "unknown instruction #{ed.data[di_addr-block.address+block.edata_ptr, 4].to_s.unpack('H*')}"} at #{Expression[di_addr]}" if $VERBOSE return 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 if not di block = di . block di_addr = di . next_addr backtrace_xrefs_di_rw ( di ) if not di_addr or di . opcode . props [ :stopexec ] or not @program . get_xrefs_x ( self , di ) . empty? delay_slot ||= [ di , @cpu . delay_slot ( di ) ] end if delay_slot di , delay = delay_slot if delay == 0 or not di_addr backtrace_xrefs_di_x ( di ) if di . opcode . props [ :stopexec ] or not di_addr ; return else break end end delay_slot [ 1 ] = delay - 1 end } ar = [ di_addr ] ar = @callback_newaddr [ block . list . last . address , ar ] || ar if callback_newaddr ar . each { | di_addr_ | backtrace ( di_addr_ , di . address , :origin => di . address , :type => :x ) } block end
disassembles a new instruction block at block.address (must be normalized)
disassembles a new instruction block at block . address ( must be normalized )
# try not to run for too long # loop usage: break if the block continues to the following instruction, else return # check collision into a known block # check self-modifying code #(-7...di.bin_length).each { |off|	# uncomment to check for unaligned rewrites #di_addr + off #next if off + x.len < 0 #} # decode instruction # do not backtrace until delay slot is finished (eg MIPS: di is a #  ret and the delay slot holds stack fixup needed to calc func_binding) # XXX if the delay slot is also xref_x or :stopexec it is ignored
block