def udiv(ir, instr, a, b, c=None): e = [] if c is None: b, c = a, b loc_div = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_except = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) e.append(ExprAssign(ir.IRDst, ExprCond(c, loc_div, loc_except))) do_except = [] do_except.append( ExprAssign(exception_flags, ExprInt(EXCEPT_DIV_BY_ZERO, exception_flags.size))) do_except.append(ExprAssign(ir.IRDst, loc_next)) blk_except = IRBlock(loc_except.loc_key, [AssignBlock(do_except, instr)]) r = ExprOp("udiv", b, c) do_div = [] do_div.append(ExprAssign(a, r)) dst = get_dst(a) if dst is not None: do_div.append(ExprAssign(ir.IRDst, r)) do_div.append(ExprAssign(ir.IRDst, loc_next)) blk_div = IRBlock(loc_div.loc_key, [AssignBlock(do_div, instr)]) return e, [blk_div, blk_except]
def sanitize_graph_head(ircfg, head): """ In multiple algorithm, the @head of the ircfg may not have predecessors. The function transform the @ircfg in order to ensure this property @ircfg: IRCFG instance @head: the location of the graph's head """ if not ircfg.predecessors(head): return original_edges = ircfg.predecessors(head) sub_head = ircfg.loc_db.add_location() # Duplicate graph, replacing references to head by sub_head replaced_expr = { ExprLoc(head, ircfg.IRDst.size): ExprLoc(sub_head, ircfg.IRDst.size) } ircfg.simplify(lambda expr: expr.replace_expr(replaced_expr)) # Duplicate head block ircfg.add_irblock(IRBlock(ircfg.loc_db, sub_head, list(ircfg.blocks[head]))) # Remove original head block ircfg.del_node(head) for src in original_edges: ircfg.add_edge(src, sub_head) # Create new head, jumping to sub_head assignblk = AssignBlock({ircfg.IRDst: ExprLoc(sub_head, ircfg.IRDst.size)}) new_irblock = IRBlock(ircfg.loc_db, head, [assignblk]) ircfg.add_irblock(new_irblock)
def eval_updt_irblock(self, irb, step=False): """ Symbolic execution of the @irb on the current state @irb: IRBlock instance @step: display intermediate steps """ assignblks = [] for index, assignblk in enumerate(irb): new_assignblk = {} links = {} for dst, src in viewitems(assignblk): src = self.propag_expr_cst(src) if dst.is_mem(): ptr = dst.ptr ptr = self.propag_expr_cst(ptr) dst = ExprMem(ptr, dst.size) new_assignblk[dst] = src if assignblk.instr is not None: for arg in assignblk.instr.args: new_arg = self.propag_expr_cst(arg) links[new_arg] = arg self.cst_propag_link[(irb.loc_key, index)] = links self.eval_updt_assignblk(assignblk) assignblks.append(AssignBlock(new_assignblk, assignblk.instr)) self.ircfg.blocks[irb.loc_key] = IRBlock(irb.loc_key, assignblks)
def add_condition_expr(ir, instr, cond, instr_ir, extra_ir): if cond == COND_AL: return instr_ir, extra_ir if not cond in tab_cond: raise ValueError('unknown condition %r' % cond) cond = tab_cond[cond] loc_next = ir.get_next_loc_key(instr) loc_next_expr = ExprLoc(loc_next, 32) loc_do = ir.loc_db.add_location() loc_do_expr = ExprLoc(loc_do, 32) dst_cond = ExprCond(cond, loc_do_expr, loc_next_expr) assert (isinstance(instr_ir, list)) has_irdst = False for e in instr_ir: if e.dst == ir.IRDst: has_irdst = True break if not has_irdst: instr_ir.append(ExprAssign(ir.IRDst, loc_next_expr)) e_do = IRBlock(loc_do, [AssignBlock(instr_ir, instr)]) e = [ExprAssign(ir.IRDst, dst_cond)] return e, [e_do] + extra_ir
def _recog_init(self, merging_var_candidates): # recognize cff loops and initiate deobfuscation self._merging_var_candidates = merging_var_candidates self.ircfg = self.ir_arch.new_ircfg_from_asmcfg(self.asmcfg) self.asmcfg.rebuild_edges() # TODO put constant propagation here when fixed in Miasm # simp = IRCFGSimplifierSSA(self.ir_arch) # from datetime import datetime # startTime = datetime.now() # ssa = simp.ircfg_to_ssa(self.ircfg, LocKey(0)) # simp.do_propagate_expressions(ssa, LocKey(0)) # self.ircfg = simp.ssa_to_unssa(ssa, LocKey(0)) # print(datetime.now() - startTime) # init_infos = self.ir_arch.arch.regs.regs_init # cst_propag_link = cst_prop.propagate_cst_expr(self.ir_arch, self.ircfg, self.asmcfg.func_addr, init_infos) # raise Exception("test") self._normalize_ircfg(self.conn) irb_bak = None if merging_var_candidates: self.pad = True new_line = AssignBlock([ExprAssign(k, k) for k in merging_var_candidates]) irb_bak = self.ircfg.blocks[LocKey(0)] new_irb = IRBlock(LocKey(0), tuple([new_line, *self.ircfg.blocks[LocKey(0)].assignblks])) self.ircfg.blocks[LocKey(0)] = new_irb self.analyses = Analyses(self.ircfg, self.asmcfg) return irb_bak
def emul(self, lifter, ctx=None, step=False): """Symbolic execution of relevant nodes according to the history Return the values of inputs nodes' elements @lifter: Lifter instance @ctx: (optional) Initial context as dictionary @step: (optional) Verbose execution Warning: The emulation is not sound if the inputs nodes depend on loop variant. """ # Init ctx_init = {} if ctx is not None: ctx_init.update(ctx) assignblks = [] # Build a single assignment block according to history last_index = len(self.relevant_loc_keys) for index, loc_key in enumerate(reversed(self.relevant_loc_keys), 1): if index == last_index and loc_key == self.initial_state.loc_key: line_nb = self.initial_state.line_nb else: line_nb = None assignblks += self.irblock_slice(self._ircfg.blocks[loc_key], line_nb).assignblks # Eval the block loc_db = lifter.loc_db temp_loc = loc_db.get_or_create_name_location("Temp") symb_exec = SymbolicExecutionEngine(lifter, ctx_init) symb_exec.eval_updt_irblock(IRBlock(loc_db, temp_loc, assignblks), step=step) # Return only inputs values (others could be wrongs) return {element: symb_exec.symbols[element] for element in self.inputs}
def block2assignblks(self, block): irblocks_list = super(mipsCGen, self).block2assignblks(block) for irblocks in irblocks_list: for blk_idx, irblock in enumerate(irblocks): has_breakflow = any(assignblock.instr.breakflow() for assignblock in irblock) if not has_breakflow: continue irs = [] for assignblock in irblock: if self.ir_arch.pc not in assignblock: irs.append(AssignBlock(assignments, assignblock.instr)) continue assignments = dict(assignblock) # Add internal branch destination assignments[self.delay_slot_dst] = assignblock[ self.ir_arch.pc] assignments[self.delay_slot_set] = m2_expr.ExprInt(1, 32) # Replace IRDst with next instruction dst_loc_key = self.ir_arch.get_next_instr( assignblock.instr) assignments[self.ir_arch.IRDst] = m2_expr.ExprLoc( dst_loc_key, 32) irs.append(AssignBlock(assignments, assignblock.instr)) irblocks[blk_idx] = IRBlock(irblock.loc_key, irs) return irblocks_list
def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False): """ Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions """ loc_key = block.loc_key ir_blocks_all = [] assignments = [] for index, instr in enumerate(block.lines): if loc_key is None: assignments = [] loc_key = self.get_loc_key_for_instr(instr) if instr.is_subcall(): assert index == len(block.lines) - 2 # Add last instruction first (before call) split = self.add_instr_to_current_state( block.lines[-1], block, assignments, ir_blocks_all, gen_pc_updt ) assert not split # Add call effects after the delay splot split = self.add_instr_to_current_state( instr, block, assignments, ir_blocks_all, gen_pc_updt ) assert split break split = self.add_instr_to_current_state( instr, block, assignments, ir_blocks_all, gen_pc_updt ) if split: ir_blocks_all.append(IRBlock(loc_key, assignments)) loc_key = None assignments = [] if loc_key is not None: ir_blocks_all.append(IRBlock(loc_key, assignments)) new_ir_blocks_all = self.post_add_asmblock_to_ircfg(block, ircfg, ir_blocks_all) for irblock in new_ir_blocks_all: ircfg.add_irblock(irblock) return new_ir_blocks_all
def gen_irblock(label, exprs_list): irs = [] for exprs in exprs_list: if isinstance(exprs, AssignBlock): irs.append(exprs) else: irs.append(AssignBlock(exprs)) irbl = IRBlock(loc_db, label, irs) return irbl
def process(self, pending, merging_val, reached_funcs): if len(self.flat_loops) == 0: # add all reached functions for func_addr, possible_merge_vars, loc_key in self.possible_merge_funcs: reached_funcs.add(func_addr) for expr, val in possible_merge_vars: pending.setdefault(func_addr, {}).setdefault(expr, set()).add(val) return None assert len(self.asmcfg.heads()) == 1 # add merging var to the ircfg if self.pad: initial_block_bak = self.ircfg.blocks[LocKey(0)] if merging_val and self.merging_var: asgn_blk = AssignBlock( [ExprAssign(self.merging_var, merging_val)]) else: asgn_blk = AssignBlock() assignblks = tuple( [asgn_blk, *self.ircfg.blocks[LocKey(0)].assignblks]) self.ircfg.blocks[LocKey(0)] = IRBlock(LocKey(0), assignblks) head = self.asmcfg.heads()[0] head_block = self.asmcfg.loc_key_to_block(head) new_head = self._deobfuscate_cff_loops( head_block, self.asmcfg.machine.mn.regs.regs_init) if self.pad: self.ircfg.blocks[LocKey(0)] = initial_block_bak if merging_val and self.merging_var: mode = self.asmcfg.mode fix_dct = { self.asmcfg.machine.mn.regs.regs_init[self.ir_arch.sp]: self.ir_arch.sp } mov = instruction_x86( "MOV", mode, [self.merging_var.replace_expr(fix_dct), merging_val]) mov.additional_info = additional_info() mov.additional_info.g1.value = 0 self.out_asmcfg.loc_key_to_block(LocKey(0)).lines.insert( 0, mov) loc_keys = self.relevant_nodes for func_addr, possible_merge_vars, loc_key in self.possible_merge_funcs: if loc_key in loc_keys: reached_funcs.add(func_addr) for expr, val in possible_merge_vars: pending.setdefault(func_addr, {}).setdefault(expr, set()).add(val) return new_head
def insert_parallel_copy(self): """ Naive Out-of-SSA from CSSA (without coalescing for now) - Replace Phi - Create room for parallel copies in Phi's parents """ ircfg = self.ssa.graph for irblock in list(viewvalues(ircfg.blocks)): if not irblock_has_phi(irblock): continue # Replace Phi with Phi's dst = new_var parallel_copies = {} for dst in self.phi_destinations[irblock.loc_key]: new_var = self.phi_new_var[dst] parallel_copies[dst] = new_var assignblks = list(irblock) assignblks[0] = AssignBlock(parallel_copies, irblock[0].instr) new_irblock = IRBlock(irblock.loc_db, irblock.loc_key, assignblks) ircfg.blocks[irblock.loc_key] = new_irblock # Insert new_var = src in each Phi's parent, at the end of the block parent_to_parallel_copies = {} parallel_copies = {} for dst in irblock[0]: new_var = self.phi_new_var[dst] for parent, src in self.phi_parent_sources[dst]: parent_to_parallel_copies.setdefault(parent, {})[new_var] = src for parent, parallel_copies in viewitems( parent_to_parallel_copies): parent = ircfg.blocks[parent] assignblks = list(parent) assignblks.append( AssignBlock(parallel_copies, parent[-1].instr)) new_irblock = IRBlock(parent.loc_db, parent.loc_key, assignblks) ircfg.blocks[parent.loc_key] = new_irblock
def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False): """ Add a native block to the current IR @block: native assembly block @gen_pc_updt: insert PC update effects between instructions """ it_hints = None it_cond = None label = block.loc_key assignments = [] ir_blocks_all = [] index = -1 while index + 1 < len(block.lines): index += 1 instr = block.lines[index] if label is None: assignments = [] label = self.get_loc_key_for_instr(instr) if instr.name.startswith("IT"): index, irblocks_it = self.do_it_block(label, index, block, assignments, gen_pc_updt) for irblocks in irblocks_it: ir_blocks_all += irblocks label = None continue split = self.add_instr_to_current_state(instr, block, assignments, ir_blocks_all, gen_pc_updt) if split: ir_blocks_all.append(IRBlock(label, assignments)) label = None assignments = [] if label is not None: ir_blocks_all.append(IRBlock(label, assignments)) new_ir_blocks_all = self.post_add_asmblock_to_ircfg( block, ircfg, ir_blocks_all) for irblock in new_ir_blocks_all: ircfg.add_irblock(irblock) return new_ir_blocks_all
def _convert_phi(self): """Inserts corresponding phi functions inplace into IRBlock at the beginning""" for loc_key in self._phinodes: irblock = self.get_block(loc_key) if irblock is None: continue assignblk = AssignBlock(self._phinodes[loc_key]) if irblock_has_phi(irblock): # If first block contains phi, we are updating an existing ssa form # so update phi assignblks = list(irblock.assignblks) out = dict(assignblks[0]) out.update(dict(assignblk)) assignblks[0] = AssignBlock(out, assignblk.instr) new_irblock = IRBlock(self.ircfg.loc_db, loc_key, assignblks) else: # insert at the beginning new_irblock = IRBlock(self.ircfg.loc_db, loc_key, [assignblk] + list(irblock.assignblks)) self.ircfg.blocks[loc_key] = new_irblock
def gen_irblock(label, exprs_list): """ Returns an IRBlock. Used only for tests purpose """ irs = [] for exprs in exprs_list: if isinstance(exprs, AssignBlock): irs.append(exprs) else: irs.append(AssignBlock(exprs)) irbl = IRBlock(loc_db, label, irs) return irbl
def casp(ir, instr, arg1, arg2, arg3): # XXX TODO: memory barrier e = [] if arg1.size == 32: regs = gpregs32_expr else: regs = gpregs64_expr index1 = regs.index(arg1) index2 = regs.index(arg2) # TODO endianness comp_value = ExprCompose(regs[index1], regs[index1 + 1]) new_value = ExprCompose(regs[index2], regs[index2 + 1]) assert arg3.is_op('preinc') ptr = arg3.args[0] data = ExprMem(ptr, comp_value.size) loc_store = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_do = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) e.append( ExprAssign( ir.IRDst, ExprCond(ExprOp("FLAG_EQ_CMP", data, comp_value), loc_do, loc_store))) e_store = [] e_store.append(ExprAssign(data, new_value)) e_store.append(ExprAssign(ir.IRDst, loc_do)) blk_store = IRBlock(loc_store.loc_key, [AssignBlock(e_store, instr)]) e_do = [] e_do.append(ExprAssign(regs[index1], data[:data.size // 2])) e_do.append(ExprAssign(regs[index1 + 1], data[data.size // 2:])) e_do.append(ExprAssign(ir.IRDst, loc_next)) blk_do = IRBlock(loc_do.loc_key, [AssignBlock(e_do, instr)]) return e, [blk_store, blk_do]
def custom_add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False, asmcfg=None): """ Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions """ loc_key = block.loc_key ir_blocks_all = [] assignments = [] self.asm_block = block for instr in block.lines: if loc_key is None: assignments = [] loc_key = self.get_loc_key_for_instr(instr) split = self.add_instr_to_current_state(instr, block, assignments, ir_blocks_all, gen_pc_updt) if split: ir_blocks_all.append(IRBlock(loc_key, assignments)) loc_key = None if len(assignments) != len(block.lines) and asmcfg: new_block = block.split(asmcfg.loc_db, self.split_offset) self.new_blocks.append(new_block) break assignments = [] if loc_key is not None: ir_blocks_all.append(IRBlock(loc_key, assignments)) new_ir_blocks_all = self.post_add_asmblock_to_ircfg( block, ircfg, ir_blocks_all) for irblock in new_ir_blocks_all: ircfg.add_irblock(irblock) return new_ir_blocks_all
def assignblk_to_irbloc(self, instr, assignblk): """ Ensure IRDst is always set in the head @assignblk of the @instr @instr: an instruction instance @assignblk: Assignblk instance """ new_assignblk = dict(assignblk) if self.ir_arch.IRDst not in assignblk: offset = instr.offset + instr.l loc_key = self.ir_arch.loc_db.get_or_create_offset_location(offset) dst = ExprLoc(loc_key, self.ir_arch.IRDst.size) new_assignblk[self.ir_arch.IRDst] = dst irs = [AssignBlock(new_assignblk, instr)] return IRBlock(self.ir_arch.get_loc_key_for_instr(instr), irs)
def add_out_reg_end(ir_arch_a, ircfg_a): # Add dummy dependency to uncover out regs affectation for loc in ircfg_a.leaves(): irblock = ircfg_a.blocks.get(loc) if irblock is None: continue regs = {} for reg in ir_arch_a.get_out_regs(irblock): regs[reg] = reg assignblks = list(irblock) new_assiblk = AssignBlock(regs, assignblks[-1].instr) assignblks.append(new_assiblk) new_irblock = IRBlock(loc_db, irblock.loc_key, assignblks) ircfg_a.blocks[loc] = new_irblock
def remove_assign_eq(self): """ Remove trivial expressions (a=a) in the current graph """ for irblock in list(viewvalues(self.ssa.graph.blocks)): assignblks = list(irblock) for i, assignblk in enumerate(assignblks): out = {} for dst, src in viewitems(assignblk): if dst == src: continue out[dst] = src assignblks[i] = AssignBlock(out, assignblk.instr) self.ssa.graph.blocks[irblock.loc_key] = IRBlock( irblock.loc_db, irblock.loc_key, assignblks)
def addIRBlock(self, newIRCFG, state, lockey): assignBlocks = [] lastAssign = None lastIndex = None for dst, src in state.items(): newAssign = AssignBlock({dst: src}) if dst == newIRCFG._irdst: lastAssign = newAssign lastIndex = len(assignBlocks) assignBlocks.append(newAssign) tmp = assignBlocks[-1] assignBlocks[-1] = lastAssign assignBlocks[lastIndex] = tmp newIRBlock = IRBlock(lockey, assignBlocks) newIRCFG.add_irblock(newIRBlock) return newIRBlock
def simplify(self): simplifier = IRCFGSimplifierCommon(self.custom_ira1) simplifier.simplify(self.ircfg, self.head) for loc in self.ircfg.leaves(): irblock = self.ircfg.blocks.get(loc) if irblock is None: continue regs = {} for reg in self.custom_ira1.get_out_regs(irblock): regs[reg] = reg assignblks = list(irblock) newAssignBlk = AssignBlock(regs, assignblks[-1].instr) assignblks.append(newAssignBlk) newIrBlock = IRBlock(irblock.loc_key, assignblks) self.ircfg.blocks[loc] = newIrBlock simplifier = CustomIRCFGSimplifierSSA(self.custom_ira2) simplifier.simplify(self.ircfg, self.head)
def remove_phi(self): """ Remove phi operators in @ifcfg @ircfg: IRDiGraph instance """ for irblock in list(viewvalues(self.ssa.graph.blocks)): assignblks = list(irblock) out = {} for dst, src in viewitems(assignblks[0]): if src.is_op('Phi'): assert set([dst]) == set(src.args) continue out[dst] = src assignblks[0] = AssignBlock(out, assignblks[0].instr) self.ssa.graph.blocks[irblock.loc_key] = IRBlock( irblock.loc_db, irblock.loc_key, assignblks)
def _fix_no_def_var(self, head): """ Replace phi source variables which are not ssa vars by ssa vars. @head: loc_key of the graph head """ var_to_insert = set() for loc_key in self._phinodes: for dst, sources in viewitems(self._phinodes[loc_key]): for src in sources.args: if src in self.ssa_variable_to_expr: continue var_to_insert.add(src) var_to_newname = {} newname_to_var = {} for var in var_to_insert: new_var = self._transform_var_lhs(var) var_to_newname[var] = new_var newname_to_var[new_var] = var # Replace non modified node used in phi with new variable self.ircfg.simplify(lambda expr: expr.replace_expr(var_to_newname)) if newname_to_var: irblock = self.ircfg.blocks[head] assignblks = list(irblock) assignblks[0:0] = [ AssignBlock(newname_to_var, assignblks[0].instr) ] self.ircfg.blocks[head] = IRBlock(self.ircfg.loc_db, head, assignblks) # Updt structure for loc_key in self._phinodes: for dst, sources in viewitems(self._phinodes[loc_key]): self._phinodes[loc_key][dst] = sources.replace_expr( var_to_newname) for var, (loc_key, index) in list(viewitems(self.ssa_to_location)): if loc_key == head: self.ssa_to_location[var] = loc_key, index + 1 for newname, var in viewitems(newname_to_var): self.ssa_to_location[newname] = head, 0 self.ssa_variable_to_expr[newname] = var self.expressions[newname] = var
def del_dst_zr(self, instr, instr_ir, extra_ir): "Writes to zero register are discarded" regs_to_fix = [WZR, XZR] instr_ir = [expr for expr in instr_ir if expr.dst not in regs_to_fix] new_irblocks = [] for irblock in extra_ir: irs = [] for assignblk in irblock: new_dsts = { dst: src for dst, src in viewitems(assignblk) if dst not in regs_to_fix } irs.append(AssignBlock(new_dsts, assignblk.instr)) new_irblocks.append(IRBlock(irblock.loc_key, irs)) return instr_ir, new_irblocks
def irbloc_fix_regs_for_mode(self, irblock, mode=64): irs = [] for assignblk in irblock: new_assignblk = dict(assignblk) for dst, src in viewitems(assignblk): del (new_assignblk[dst]) # Special case for 64 bits: # If destination is a 32 bit reg, zero extend the 64 bit reg if (isinstance(dst, ExprId) and dst.size == 32 and dst in replace_regs): src = src.zeroExtend(64) dst = replace_regs[dst].arg dst = self.expr_fix_regs_for_mode(dst) src = self.expr_fix_regs_for_mode(src) new_assignblk[dst] = src irs.append(AssignBlock(new_assignblk, assignblk.instr)) return IRBlock(irblock.loc_key, irs)
def _convert_block(irblock, ssa_list): """ Transforms an IRBlock inplace into SSA :param irblock: IRBlock to be transformed :param ssa_list: list of SSA expressions """ # iterator over SSA expressions ssa_iter = iter(ssa_list) new_irs = [] # walk over IR blocks' assignblocks for assignblk in irblock.assignblks: # list of instructions instructions = [] # insert SSA instructions for _ in assignblk: instructions.append(next(ssa_iter)) # replace instructions of assignblock in IRBlock new_irs.append(AssignBlock(instructions, assignblk.instr)) return IRBlock(irblock.loc_db, irblock.loc_key, new_irs)
def tne(ir, instr, arg1, arg2): e = [] loc_except, loc_except_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) do_except = [] do_except.append(m2_expr.ExprAssign(exception_flags, m2_expr.ExprInt( EXCEPT_DIV_BY_ZERO, exception_flags.size))) do_except.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) blk_except = IRBlock(ir.loc_db, loc_except, [AssignBlock(do_except, instr)]) cond = arg1 ^ arg2 e = [] e.append(m2_expr.ExprAssign(ir.IRDst, m2_expr.ExprCond(cond, loc_next_expr, loc_except_expr))) return e, [blk_except]
def getMaxIRCFG(self): if self.maxIRCFG is not None: return self.maxIRCFG else: self.maxIRCFG = self.maxIRA1.new_ircfg_from_asmcfg(self.cfg) simplifier = IRCFGSimplifierCommon(self.maxIRA1) simplifier.simplify(self.maxIRCFG, self.head) for loc in self.maxIRCFG.leaves(): irblock = self.maxIRCFG.blocks.get(loc) if irblock is None: continue regs = {} for reg in self.maxIRA1.get_out_regs(irblock): regs[reg] = reg assignblks = list(irblock) newAssignBlk = AssignBlock(regs, assignblks[-1].instr) assignblks.append(newAssignBlk) newIrBlock = IRBlock(irblock.loc_key, assignblks) self.maxIRCFG.blocks[loc] = newIrBlock simplifier = CustomIRCFGSimplifierSSA(self.maxIRA2) simplifier.simplify(self.maxIRCFG, self.head) self.maxDefUse = DiGraphDefUse(ReachingDefinitions(self.maxIRCFG)) return self.maxIRCFG
def call_effects(self, ad, instr): call_assignblk = AssignBlock([ ExprAssign( self.ret_reg, ExprOp( 'call_func_ret', ad, self.arch.regs.R0, self.arch.regs.R1, self.arch.regs.R2, self.arch.regs.R3, )), ExprAssign(self.sp, ExprOp('call_func_stack', ad, self.sp)), ], instr) cond = instr.additional_info.cond if cond == 14: # COND_ALWAYS: return [call_assignblk], [] # Call is a conditional instruction cond = tab_cond[cond] loc_next = self.get_next_loc_key(instr) loc_next_expr = ExprLoc(loc_next, 32) loc_do = self.loc_db.add_location() loc_do_expr = ExprLoc(loc_do, 32) dst_cond = ExprCond(cond, loc_do_expr, loc_next_expr) call_assignblks = [ call_assignblk, AssignBlock([ExprAssign(self.IRDst, loc_next_expr)], instr), ] e_do = IRBlock(loc_do, call_assignblks) assignblks_out = [ AssignBlock([ExprAssign(self.IRDst, dst_cond)], instr) ] return assignblks_out, [e_do]
def irblock_slice(self, irb, max_line=None): """Slice of the dependency nodes on the irblock @irb @irb: irbloc instance """ assignblks = [] line2elements = {} for depnode in self.relevant_nodes: if depnode.loc_key != irb.loc_key: continue line2elements.setdefault(depnode.line_nb, set()).add(depnode.element) for line_nb, elements in sorted(viewitems(line2elements)): if max_line is not None and line_nb >= max_line: break assignmnts = {} for element in elements: if element in irb[line_nb]: # constants, loc_key, ... are not in destination assignmnts[element] = irb[line_nb][element] assignblks.append(AssignBlock(assignmnts)) return IRBlock(irb.loc_db, irb.loc_key, assignblks)