def _handle_Assignment(self, stmt_idx: int, stmt: Assignment, block: Block): new_dst = self._handle_expr(0, stmt.dst, stmt_idx, stmt, block) new_src = self._handle_expr(1, stmt.src, stmt_idx, stmt, block) if new_dst is not None or new_src is not None: new_stmt = Assignment(stmt.idx, stmt.dst if new_dst is None else new_dst, stmt.src if new_src is None else new_src, **stmt.tags) return new_stmt return None
def _replace_and_build( block, replacements, replace_assignment_dsts: bool = False) -> Tuple[bool, 'Block']: new_statements = block.statements[::] replaced = False for codeloc, repls in replacements.items(): for old, new in repls.items(): stmt = new_statements[codeloc.stmt_idx] if isinstance(old, Load) and not isinstance(stmt, Call): # skip memory-based replacement for non-Call statements continue if stmt == old: # replace this statement r = True new_stmt = new else: # replace the expressions involved in this statement if isinstance(stmt, Call) and isinstance( new, Call) and old == stmt.ret_expr: # special case: do not replace the ret_expr of a call statement to another call statement r = False new_stmt = None elif isinstance( stmt, Assignment) and not replace_assignment_dsts: # special case: do not replace the dst new_stmt = None if stmt.src == old: r = True new_src = new.copy() else: r, new_src = stmt.src.replace(old, new) if r: new_stmt = Assignment(stmt.idx, stmt.dst, new_src, **stmt.tags) else: r, new_stmt = stmt.replace(old, new) if r: replaced = True new_statements[codeloc.stmt_idx] = new_stmt if not replaced: return False, block new_block = block.copy() new_block.statements = new_statements return True, new_block
def _handle_Assignment(self, stmt_idx: int, stmt: Assignment, block: Optional[Block]): changed = False dst = self._handle_expr(0, stmt.dst, stmt_idx, stmt, block) if dst is not None and dst is not stmt.dst: changed = True else: dst = stmt.dst src = self._handle_expr(1, stmt.src, stmt_idx, stmt, block) if src is not None and src is not stmt.src: changed = True else: src = stmt.src if changed: # update the statement directly in the block new_stmt = Assignment(stmt.idx, dst, src, **stmt.tags) block.statements[stmt_idx] = new_stmt
def _peephole_optimize_ConstantDereference(self, stmt: Assignment): if isinstance(stmt.src, Load) and isinstance(stmt.src.addr, Const): # is it loading from a read-only section? sec = self.project.loader.find_section_containing( stmt.src.addr.value) if sec is not None and sec.is_readable and not sec.is_writable: # do we know the value that it's reading? try: val = self.project.loader.memory.unpack_word( stmt.src.addr.value, size=self.project.arch.bytes) except KeyError: return stmt return Assignment( stmt.idx, stmt.dst, Const(None, None, val, stmt.src.size * self.project.arch.byte_width), **stmt.tags, ) return stmt
def _handle_Assignment(self, stmt_idx: int, stmt: Assignment, block: Optional[Block]): # override the base handler and make sure we do not replace .dst with a Call expression changed = False dst = self._handle_expr(0, stmt.dst, stmt_idx, stmt, block) if dst is not None and dst is not stmt.dst and not isinstance( dst, Call): changed = True else: dst = stmt.dst src = self._handle_expr(1, stmt.src, stmt_idx, stmt, block) if src is not None and src is not stmt.src: changed = True else: src = stmt.src if changed: # update the statement directly in the block new_stmt = Assignment(stmt.idx, dst, src, **stmt.tags) block.statements[stmt_idx] = new_stmt