def enumerate_basicblocks_statically(instructions): """ Return a list of basicblock after statically parsing given instructions """ basicblocks = list() index = 0 # create the first block new_block = False block = BasicBlock(instructions[0].offset, instructions[0], name='block_%x' % instructions[0].offset) for inst in instructions: if new_block: block = BasicBlock(inst.offset, inst, name='block_%x' % inst.offset) new_block = False # add current instruction to the basicblock block.instructions.append(inst) # absolute JUMP if inst.is_branch_unconditional: block.type = BASICBLOCK_UNCONDITIONAL logging.debug("unconditional %x : %s", inst.offset, inst.name) # conditionnal JUMPI elif inst.is_branch_conditional: block.type = BASICBLOCK_CONDITIONAL logging.debug("conditional %x : %s", inst.offset, inst.name) # Halt instruction : RETURN, STOP, ... elif inst.is_halt: # and inst != instructions[-1]: block.type = BASICBLOCK_TERMINAL logging.debug("terminal %x : %s", inst.offset, inst.name) # just falls to the next instruction elif inst != instructions[-1] and \ instructions[index + 1].name == 'JUMPDEST': block.type = BASICBLOCK_FALLTHROUGH logging.debug("fallthrough %x : %s", inst.offset, inst.name) # last instruction of the entire bytecode elif inst == instructions[-1]: block.type = BASICBLOCK_TERMINAL if block.type != BASICBLOCK_DEFAULT: block.end_offset = inst.offset_end block.end_instr = inst basicblocks.append(block) new_block = True index += 1 return basicblocks
def enumerate_basicblocks_statically(instructions): """ Return a list of basicblock after statically parsing given instructions """ basicblocks = list() xrefs = enumerate_xref(instructions) # create the first block new_block = True for inst in instructions: if new_block: block = BasicBlock(start_offset=inst.offset, start_instr=inst, name='block_%x' % inst.offset) new_block = False # add current instruction to the basicblock block.instructions.append(inst) # next instruction in list_ref if (inst.offset_end + 1) in xrefs: # absolute JUMP if inst.is_branch_unconditional: block.type = BASICBLOCK_UNCONDITIONAL logging.debug("unconditional %x : %s", inst.offset, inst.name) # conditionnal JUMPI / JUMPIF / ... elif inst.is_branch_conditional: block.type = BASICBLOCK_CONDITIONAL logging.debug("conditional %x : %s", inst.offset, inst.name) # Halt instruction : RETURN, STOP, RET, ... elif inst.is_halt: # and inst != func.instructions[-1]: block.type = BASICBLOCK_TERMINAL logging.debug("terminal %x : %s", inst.offset, inst.name) # just falls to the next instruction else: block.type = BASICBLOCK_FALLTHROUGH logging.debug("fallthrough %x : %s", inst.offset, inst.name) block.end_offset = inst.offset_end block.end_instr = inst basicblocks.append(block) new_block = True # add the last block basicblocks.append(block) basicblocks = list(set(basicblocks)) return basicblocks