class Metasm::InstructionBlock
holds a list of contiguous decoded instructions, forming an uninterrupted block (except for eg CPU exceptions) most attributes are either a value or an array of values, use the associated iterator.
Attributes
address of the first instruction
array of BacktraceTrace when a new code path comes to us, it should be backtracked for the values of :r/:w/:x using btt with no address for internal use only (block splitting): btt with an address
pointer to raw data
pointer to raw data
address of instructions executed indirectly through us (callback in a subfunction, SEH…) XXX #from_indirect is not populated for now
address of instructions giving control directly to us includes addr of normal instruction when call flow continues to us past the end of the preceding block does not include addresses of subfunction return instructions may be nil or an array
address of an instruction that calls a subfunction which returns to us
list of DecodedInstructions
address of instructions executed indirectly through us (callback in a subfunction, SEH…) XXX #from_indirect is not populated for now
address of instructions called/jumped to
address of instruction executed after a called subfunction returns
Public Class Methods
create a new InstructionBlock based at address also accepts a DecodedInstruction or an Array of them to initialize from
# File metasm/disassemble.rb, line 169 def initialize(arg0, edata=nil, edata_ptr=nil) @list = [] case arg0 when DecodedInstruction @address = arg0.address add_di(arg0) when Array @address = arg0.first.address if not arg0.empty? arg0.each { |di| add_di(di) } else @address = arg0 end edata_ptr ||= edata ? edata.ptr : 0 @edata, @edata_ptr = edata, edata_ptr @backtracked_for = [] end
Public Instance Methods
adds a decodedinstruction to the block list, updates di.block and di.block_offset
# File metasm/disassemble.rb, line 211 def add_di(di) di.block = self di.block_offset = bin_length di.address ||= @address + di.block_offset @list << di end
adds an address to the from_normal/from_subfuncret list
# File metasm/disassemble_api.rb, line 11 def add_from(addr, type=:normal) send "add_from_#{type}", addr end
# File metasm/disassemble_api.rb, line 22 def add_from_indirect(addr) @from_indirect ||= [] @from_indirect |= [addr] end
# File metasm/disassemble_api.rb, line 14 def add_from_normal(addr) @from_normal ||= [] @from_normal |= [addr] end
# File metasm/disassemble_api.rb, line 18 def add_from_subfuncret(addr) @from_subfuncret ||= [] @from_subfuncret |= [addr] end
# File metasm/disassemble_api.rb, line 42 def add_to(addr, type=:normal) send "add_to_#{type}", addr end
# File metasm/disassemble_api.rb, line 53 def add_to_indirect(addr) @to_indirect ||= [] @to_indirect |= [addr] end
# File metasm/disassemble_api.rb, line 45 def add_to_normal(addr) @to_normal ||= [] @to_normal |= [addr] end
# File metasm/disassemble_api.rb, line 49 def add_to_subfuncret(addr) @to_subfuncret ||= [] @to_subfuncret |= [addr] end
# File metasm/disassemble.rb, line 186 def bin_length (di = @list.last) ? di.block_offset + di.bin_length : 0 end
iterates over every from address, yields [address, type in [:normal, :subfuncret, :indirect]]
# File metasm/disassemble_api.rb, line 27 def each_from each_from_normal { |a| yield a, :normal } each_from_subfuncret { |a| yield a, :subfuncret } each_from_indirect { |a| yield a, :indirect } end
# File metasm/disassemble_api.rb, line 38 def each_from_indirect(&b) @from_indirect.each(&b) if from_indirect end
# File metasm/disassemble_api.rb, line 32 def each_from_normal(&b) @from_normal.each(&b) if from_normal end
yields all from that are not in the same subfunction as this block
# File metasm/disassemble_api.rb, line 80 def each_from_otherfunc(dasm, &b) @from_normal.each(&b) if from_normal and dasm.function[address] @from_subfuncret.each(&b) if from_subfuncret and dasm.function[address] @from_indirect.each(&b) if from_indirect end
yields all from that are from the same function
# File metasm/disassemble_api.rb, line 73 def each_from_samefunc(dasm, &b) return if dasm.function[address] @from_subfuncret.each(&b) if from_subfuncret @from_normal.each(&b) if from_normal end
# File metasm/disassemble_api.rb, line 35 def each_from_subfuncret(&b) @from_subfuncret.each(&b) if from_subfuncret end
# File metasm/disassemble_api.rb, line 57 def each_to each_to_normal { |a| yield a, :normal } each_to_subfuncret { |a| yield a, :subfuncret } each_to_indirect { |a| yield a, :indirect } end
# File metasm/disassemble_api.rb, line 68 def each_to_indirect(&b) @to_indirect.each(&b) if to_indirect end
# File metasm/disassemble_api.rb, line 62 def each_to_normal(&b) @to_normal.each(&b) if to_normal end
yields all to that are not in the same subfunction as this block
# File metasm/disassemble_api.rb, line 96 def each_to_otherfunc(dasm) each_to { |to, type| to = dasm.normalize(to) yield to if type == :indirect or dasm.function[to] or not dasm.decoded[to] } end
yields all to that are in the same subfunction as this block
# File metasm/disassemble_api.rb, line 87 def each_to_samefunc(dasm) each_to { |to, type| next if type != :normal and type != :subfuncret to = dasm.normalize(to) yield to if not dasm.function[to] } end
# File metasm/disassemble_api.rb, line 65 def each_to_subfuncret(&b) @to_subfuncret.each(&b) if to_subfuncret end
# File metasm/disassemble_api.rb, line 109 def from_otherfunc(dasm) ary = [] each_from_otherfunc(dasm) { |a| ary << a } ary end
returns the array used in #each_from_samefunc
# File metasm/disassemble_api.rb, line 104 def from_samefunc(dasm) ary = [] each_from_samefunc(dasm) { |a| ary << a } ary end
splits the current block into a new one with all di from address addr to end caller is responsible for rebacktracing new.bt_for to regenerate correct old.btt/new.btt
# File metasm/disassemble.rb, line 192 def split(addr) raise "invalid split @#{Expression[addr]}" if not idx = @list.index(@list.find { |di| di.address == addr }) or idx == 0 off = @list[idx].block_offset new_b = self.class.new(addr, @edata, @edata_ptr + off) new_b.add_di @list.delete_at(idx) while @list[idx] new_b.to_normal, @to_normal = to_normal, new_b.to_normal new_b.to_subfuncret, @to_subfuncret = to_subfuncret, new_b.to_subfuncret new_b.add_from @list.last.address add_to new_b.address @backtracked_for.delete_if { |btt| if btt.address and new_b.list.find { |di| di.address == btt.address } new_b.backtracked_for << btt true end } new_b end
# File metasm/disassemble_api.rb, line 119 def to_otherfunc(dasm) ary = [] each_to_otherfunc(dasm) { |a| ary << a } ary end
# File metasm/disassemble_api.rb, line 114 def to_samefunc(dasm) ary = [] each_to_samefunc(dasm) { |a| ary << a } ary end