Ejemplo n.º 1
0
    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
Ejemplo n.º 2
0
    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
Ejemplo n.º 3
0
    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
Ejemplo n.º 5
0
    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