def lhs_ast(self, astree: AbstractSyntaxTree, iaddr: str,
                xdata: InstrXData) -> Tuple[ASTLval, List[ASTInstruction]]:
        def indirect_lhs(
                rtype: Optional[BCTyp]
        ) -> Tuple[ASTLval, List[ASTInstruction]]:
            tmplval = astree.mk_returnval_variable_lval(iaddr, rtype)
            tmprhs = astree.mk_lval_expr(tmplval)
            reglval = astree.mk_register_variable_lval("R0")
            return (tmplval, [astree.mk_assign(reglval, tmprhs)])

        calltarget = xdata.call_target(self.ixd)
        tgtname = calltarget.name
        models = ModelsAccess()
        if astree.has_symbol(tgtname):
            fnsymbol = astree.symbol(tgtname)
            if fnsymbol.returns_void:
                return (astree.mk_ignored_lval(), [])
            else:
                return indirect_lhs(fnsymbol.vtype)
        elif models.has_so_function_summary(tgtname):
            summary = models.so_function_summary(tgtname)
            returntype = summary.signature.returntype
            if returntype.is_named_type:
                returntype = cast(MNamedType, returntype)
                typename = returntype.typename
                if typename == "void" or typename == "VOID":
                    return (astree.mk_ignored_lval(), [])
                else:
                    return indirect_lhs(None)
            else:
                return indirect_lhs(None)
        else:
            return indirect_lhs(None)
예제 #2
0
    def assembly_ast(self, astree: AbstractSyntaxTree, iaddr: str,
                     bytestring: str,
                     xdata: InstrXData) -> List[AST.ASTInstruction]:
        regsop = self.operands[1]
        if not regsop.is_register_list:
            raise UF.CHBError("Argument to push is not a register list")

        (splval, _, _) = self.operands[0].ast_lvalue(astree)
        (sprval, _, _) = self.operands[0].ast_rvalue(astree)

        instrs: List[AST.ASTInstruction] = []
        registers = regsop.registers
        sp_decr = 4 * len(registers)
        sp_offset = sp_decr
        for r in registers:
            sp_offset_c = astree.mk_integer_constant(sp_offset)
            addr = astree.mk_binary_op("minus", sprval, sp_offset_c)
            lhs = astree.mk_memref_lval(addr)
            rhs = astree.mk_register_variable_expr(r)
            instrs.append(astree.mk_assign(lhs, rhs))
            sp_offset -= 4
        sp_decr_c = astree.mk_integer_constant(sp_decr)
        sp_rhs = astree.mk_binary_op("minus", sprval, sp_decr_c)
        instrs.append(astree.mk_assign(splval, sp_rhs))
        astree.add_instruction_span(instrs[0].id, iaddr, bytestring)
        return instrs
예제 #3
0
def field_at_offset(compinfo: "BCCompInfo", offsetvalue: int,
                    astree: AbstractSyntaxTree) -> AST.ASTOffset:
    (finfo, r) = compinfo.field_at_offset(offsetvalue)

    if finfo.fieldtype.is_struct:
        fcompinfo = cast("BCTypComp", finfo.fieldtype).compinfo
        foffset = field_at_offset(fcompinfo, r, astree)
        return astree.mk_field_offset(finfo.fieldname,
                                      finfo.fieldtype,
                                      offset=foffset)
    elif r == 0:
        return astree.mk_field_offset(finfo.fieldname, finfo.fieldtype)
    elif finfo.fieldtype.is_array:
        ftype = cast("BCTypArray", finfo.fieldtype)
        elsize = ftype.tgttyp.byte_size()
        index = r // elsize
        ioffset = astree.mk_scalar_index_offset(index)
        return astree.mk_field_offset(finfo.fieldname,
                                      finfo.fieldtype,
                                      offset=ioffset)
    else:
        raise UF.CHBError("No field found at offset: " + str(offsetvalue) +
                          " in struct " + compinfo.cname +
                          " (Offsets found: " + ", ".join(
                              (str(f[0]) + ":" + str(f[1].fieldtype) + " " +
                               f[1].fieldname)
                              for f in compinfo.fieldoffsets()) + ")")
예제 #4
0
def xvariable_to_ast_lval(xv: X.XVariable,
                          astree: AbstractSyntaxTree) -> AST.ASTLval:
    """Convert a CHIF variable to an AST Lval node."""

    if xv.is_tmp:
        return astree.mk_temp_lval()

    elif xv.is_register_variable:
        xvden = cast("VRegisterVariable", xv.denotation)
        reg = xvden.register
        if reg.is_mips_register:
            mipsreg = cast("MIPSRegister", reg)
            name = "mips_" + mipsreg.name
        else:
            name = str(xv)
        return astree.mk_register_variable_lval(name)

    elif xv.is_memory_variable:
        xvmem = cast("VMemoryVariable", xv.denotation)
        return vmemory_variable_to_ast_lval(xvmem, astree)

    elif xv.is_auxiliary_variable:
        xvaux = cast("VAuxiliaryVariable", xv.denotation)
        return vauxiliary_variable_to_ast_lval(xvaux, astree)

    else:
        print("other: " + str(xv))
        return astree.mk_variable_lval(str(xv))
 def assembly_ast(self, astree: AbstractSyntaxTree, iaddr: str,
                  bytestring: str,
                  xdata: InstrXData) -> List[ASTInstruction]:
     msg = (iaddr + ": " + bytestring + "  " + self.mnemonic + " " +
            self.operandstring + ": " + self.annotation(xdata))
     astree.add_instruction_unsupported(self.mnemonic, msg)
     return []
 def ast(self, astree: AbstractSyntaxTree, iaddr: str, bytestring: str,
         xdata: InstrXData) -> List[AST.ASTInstruction]:
     rhs = XU.xxpr_to_ast_expr(xdata.xprs[1], astree)
     lhs = XU.xvariable_to_ast_lval(xdata.vars[0], astree)
     assign = astree.mk_assign(lhs, rhs)
     astree.add_instruction_span(assign.id, iaddr, bytestring)
     return [assign]
예제 #7
0
def xcompound_to_ast_expr(xc: X.XprCompound,
                          astree: AbstractSyntaxTree) -> AST.ASTExpr:
    """Convert a compound expression to an AST Expr node."""

    op = xc.operator
    operands = xc.operands

    if len(operands) == 1:
        op1 = xxpr_to_ast_expr(operands[0], astree)
        return astree.mk_unary_op(op, op1)

    elif len(operands) == 2:
        if xc.is_stack_address:
            stackoffset = xc.stack_address_offset()
            rhslval = astree.mk_stack_variable_lval(stackoffset)
            return astree.mk_address_of(rhslval)
        else:
            op1 = xxpr_to_ast_expr(operands[0], astree)
            op2 = xxpr_to_ast_expr(operands[1], astree)
            if op1.ctype is not None and op in ["plus", "minus"]:
                return xtyped_expr_to_ast_expr(op, op1, op2, astree)
            else:
                return astree.mk_binary_op(op, op1, op2)

    else:
        raise UF.CHBError("AST conversion of compound expression " + str(xc) +
                          " not yet supported")
 def ast(self, astree: AbstractSyntaxTree, iaddr: str, bytestring: str,
         xdata: InstrXData) -> List[AST.ASTInstruction]:
     (rhs, _, _) = self.operands[0].ast_rvalue(astree)
     lhs = xdata.vars[0]
     lval = XU.xvariable_to_ast_lval(lhs, astree)
     assign = astree.mk_assign(lval, rhs)
     astree.add_instruction_span(assign.id, iaddr, bytestring)
     return [assign]
 def assembly_ast(self, astree: AbstractSyntaxTree, iaddr: str,
                  bytestring: str,
                  xdata: InstrXData) -> List[AST.ASTInstruction]:
     (rhs, preinstrs, postinstrs) = self.operands[1].ast_rvalue(astree)
     (lhs, _, _) = self.operands[0].ast_lvalue(astree)
     assign = astree.mk_assign(lhs, rhs)
     astree.add_instruction_span(assign.id, iaddr, bytestring)
     return preinstrs + [assign] + postinstrs
예제 #10
0
def stack_variable_to_ast_lval(offset: "VMemoryOffset",
                               astree: AbstractSyntaxTree) -> AST.ASTLval:
    """TODO: split up."""

    if offset.is_constant_value_offset:
        return astree.mk_stack_variable_lval(offset.offsetvalue())

    print("stack variable: " + str(offset))
    return astree.mk_variable_lval("stack: " + str(offset))
예제 #11
0
 def assembly_ast(self, astree: AbstractSyntaxTree, iaddr: str,
                  bytestring: str,
                  xdata: InstrXData) -> List[ASTInstruction]:
     (lhs, _, _) = self.operands[0].ast_lvalue(astree)
     (op1, _, _) = self.operands[1].ast_rvalue(astree)
     (op2, _, _) = self.operands[2].ast_rvalue(astree)
     binop = astree.mk_binary_op("minus", op1, op2)
     result = astree.mk_assign(lhs, binop)
     astree.add_instruction_span(result.id, iaddr, bytestring)
     return [result]
예제 #12
0
 def assembly_ast(self, astree: AbstractSyntaxTree, iaddr: str,
                  bytestring: str,
                  xdata: InstrXData) -> List[AST.ASTInstruction]:
     (rhs1, preinstrs1, postinstrs1) = self.operands[1].ast_rvalue(astree)
     (rhs2, preinstrs2, postinstrs2) = self.operands[2].ast_rvalue(astree)
     (lhs, _, _) = self.operands[0].ast_lvalue(astree)
     binop = astree.mk_binary_op("band", rhs1, rhs2)
     assign = astree.mk_assign(lhs, binop)
     astree.add_instruction_span(assign.id, iaddr, bytestring)
     return preinstrs1 + preinstrs2 + [assign] + postinstrs1 + postinstrs2
 def assembly_ast(self, astree: AbstractSyntaxTree, iaddr: str,
                  bytestring: str,
                  xdata: InstrXData) -> List[AST.ASTInstruction]:
     if len(xdata.vars) == 1 and len(xdata.xprs) == 1:
         lhs = astree.mk_variable_lval(str(xdata.vars[0]))
         rhs = XU.xxpr_to_ast_expr(xdata.xprs[0], astree)
         assign = astree.mk_assign(lhs, rhs)
         astree.add_instruction_span(assign.id, iaddr, bytestring)
         return [assign]
     else:
         return []
예제 #14
0
 def target_expr_ast(self, astree: AbstractSyntaxTree,
                     xdata: InstrXData) -> ASTExpr:
     calltarget = xdata.call_target(self.ixd)
     tgtname = calltarget.name
     if calltarget.is_app_target:
         apptgt = cast("AppTarget", calltarget)
         return astree.mk_global_variable_expr(tgtname,
                                               globaladdress=int(
                                                   str(apptgt.address), 16))
     else:
         return astree.mk_global_variable_expr(tgtname)
 def assembly_ast(self, astree: AbstractSyntaxTree, iaddr: str,
                  bytestring: str,
                  xdata: InstrXData) -> List[AST.ASTInstruction]:
     (lhs1, preinstrs1, postinstrs1) = self.operands[4].ast_lvalue(astree)
     (lhs2, preinstrs2, postinstrs2) = self.operands[5].ast_lvalue(astree)
     (rhs1, _, _) = self.operands[0].ast_rvalue(astree)
     (rhs2, _, _) = self.operands[1].ast_rvalue(astree)
     assign1 = astree.mk_assign(lhs1, rhs1)
     assign2 = astree.mk_assign(lhs2, rhs2)
     astree.add_instruction_span(assign1.id, iaddr, bytestring)
     return (preinstrs1 + preinstrs2 + [assign1, assign2] + postinstrs1 +
             postinstrs2)
예제 #16
0
def vfunctionreturn_value_to_ast_lval(
        vconstvar: "VFunctionReturnValue",
        astree: AbstractSyntaxTree) -> AST.ASTLval:

    vtype = None
    if vconstvar.has_call_target():
        calltarget = str(vconstvar.call_target())
        if astree.has_symbol(calltarget):
            vinfo = astree.symbol(calltarget)
            vtype = vinfo.vtype

    return astree.mk_returnval_variable_lval(vconstvar.callsite, vtype)
예제 #17
0
def global_variable_to_ast_lval(offset: "VMemoryOffset",
                                astree: AbstractSyntaxTree) -> AST.ASTLval:

    if offset.is_constant_value_offset:
        gaddr = hex(offset.offsetvalue())
        gvname = astree.global_variable_name(gaddr)
        if gvname is None:
            gvname = "gv_" + gaddr
        return astree.mk_global_variable_lval(gvname,
                                              globaladdress=int(gaddr, 16))

    print("global-variable: " + "gv_" + str(offset))
    return astree.mk_variable_lval("gv_" + str(offset))
 def assembly_ast(
         self,
         astree: AbstractSyntaxTree,
         iaddr: str,
         bytestring: str,
         xdata: InstrXData) -> List[AST.ASTInstruction]:
     if xdata.instruction_is_subsumed():
         return []
     else:
         (lhs, _, _) = self.operands[0].ast_lvalue(astree)
         (rhs, _, _) = self.operands[1].ast_rvalue(astree)
         assign = astree.mk_assign(lhs, rhs)
         astree.add_instruction_span(assign.id, iaddr, bytestring)
         return [assign]
예제 #19
0
 def assembly_ast_condition(self, astree: AbstractSyntaxTree, iaddr: str,
                            bytestring: str,
                            xdata: InstrXData) -> Optional[ASTExpr]:
     ftconds = self.ft_conditions(xdata)
     if len(ftconds) == 2:
         tcond = ftconds[1]
         if tcond.is_constant:
             astcond = XU.xxpr_to_ast_expr(xdata.xprs[2], astree)
         else:
             astcond = XU.xxpr_to_ast_expr(tcond, astree)
         astree.add_instruction_span(astcond.id, iaddr, bytestring)
         return astcond
     else:
         return None
 def ast(self, astree: AbstractSyntaxTree, iaddr: str, bytestring: str,
         xdata: InstrXData) -> List[AST.ASTInstruction]:
     (rhs1, _, _) = self.operands[0].ast_rvalue(astree)
     (rhs2, _, _) = self.operands[1].ast_rvalue(astree)
     lhs1 = str(xdata.vars[0])
     lhs2 = str(xdata.vars[1])
     if lhs1.endswith("[0]"):
         lhs1 = "*" + lhs1[:-3]
     lval1 = astree.mk_variable_lval(lhs1)
     lval2 = astree.mk_variable_lval(lhs2)
     assign1 = astree.mk_assign(lval1, rhs1)
     assign2 = astree.mk_assign(lval2, rhs2)
     astree.add_instruction_span(assign1.id, iaddr, bytestring)
     astree.add_instruction_span(assign2.id, iaddr, bytestring)
     return [assign1, assign2]
예제 #21
0
def is_struct_field_address(xpr: X.XXpr, astree: AbstractSyntaxTree) -> bool:
    """Return true if the expression is the address of a known struct."""

    if xpr.is_int_constant:
        return astree.is_struct_field_address(xpr.intvalue)

    return False
 def ast_rvalue(
     self, astree: AbstractSyntaxTree
 ) -> Tuple[AST.ASTExpr, List[AST.ASTInstruction],
            List[AST.ASTInstruction]]:
     (lval, preinstrs, postinstrs) = self.ast_lvalue(astree)
     rval = astree.mk_lval_expr(lval)
     return (rval, preinstrs, postinstrs)
 def ast(
         self,
         astree: AbstractSyntaxTree,
         iaddr: str,
         bytestring: str,
         xdata: InstrXData) -> List[AST.ASTInstruction]:
     if xdata.instruction_is_subsumed():
         return []
     else:
         lhs = XU.xvariable_to_ast_lval(xdata.vars[0], astree)
         rhs = XU.xxpr_to_ast_expr(xdata.xprs[0], astree)
         # (lhs, _, _) = self.operands[0].ast_lvalue(astree)
         # (rhs, _, _) = self.operands[1].ast_rvalue(astree)
         assign = astree.mk_assign(lhs, rhs)
         astree.add_instruction_span(assign.id, iaddr, bytestring)
         return [assign]
 def ast_rvalue(
     self, astree: AbstractSyntaxTree
 ) -> Tuple[AST.ASTExpr, List[AST.ASTInstruction],
            List[AST.ASTInstruction]]:
     gvname = "gv_" + self.address.get_hex()
     gv = astree.mk_global_variable_expr(
         gvname, globaladdress=self.address.get_int())
     return (gv, [], [])
예제 #25
0
def xxpr_to_struct_field_address_expr(
        xpr: X.XXpr, astree: AbstractSyntaxTree) -> AST.ASTExpr:
    """Return a struct field as an address expression."""

    if not is_struct_field_address(xpr, astree):
        raise UF.CHBError("Expression " + str(xpr) + " is not a struct field")

    return astree.get_struct_field_address(xpr.intvalue)
예제 #26
0
def xtyped_expr_to_ast_expr(op: str, op1: AST.ASTExpr, op2: AST.ASTExpr,
                            astree: AbstractSyntaxTree) -> AST.ASTExpr:
    """Determine if expression needs different representation based on type."""

    if op1.ctype is None:
        raise UF.CHBError("Expression is not typed: " + str(op1))

    if op1.ctype.is_pointer and op2.is_integer_constant:
        op2 = cast(AST.ASTIntegerConstant, op2)
        tgttype = cast("BCTypPtr", op1.ctype).tgttyp
        if tgttype.is_struct:
            compinfo = cast("BCTypComp", tgttype).compinfo
            fieldoffset = field_at_offset(compinfo, op2.cvalue, astree)
            lval = astree.mk_memref_lval(op1, fieldoffset)
            return astree.mk_address_of(lval)

    return astree.mk_binary_op(op, op1, op2)
예제 #27
0
def vinitregister_value_to_ast_lval(vconstvar: "VInitialRegisterValue",
                                    astree: AbstractSyntaxTree) -> AST.ASTLval:

    if vconstvar.is_argument_value:
        argindex = vconstvar.argument_index()
        funarg = astree.function_argument(argindex)
        if funarg:
            return astree.mk_register_variable_lval(funarg.name,
                                                    vtype=funarg.typ,
                                                    parameter=argindex)
        else:
            return astree.mk_register_variable_lval(str(vconstvar.register))

    elif vconstvar.register.is_stack_pointer:
        return astree.mk_register_variable_lval("base_sp")
    else:
        print("Initial Register Value: " + str(vconstvar.register))
        return astree.mk_register_variable_lval(str(vconstvar.register))
예제 #28
0
 def assembly_ast(self, astree: AbstractSyntaxTree, iaddr: str,
                  bytestring: str,
                  xdata: InstrXData) -> List[ASTInstruction]:
     lhs = astree.mk_register_variable_lval("R0")
     tgt = self.operands[0]
     if tgt.is_absolute:
         tgtaddr = cast(ARMAbsoluteOp, tgt.opkind)
         if self.app.has_function_name(tgtaddr.address.get_hex()):
             faddr = tgtaddr.address.get_hex()
             fnsymbol = self.app.function_name(faddr)
             tgtxpr: ASTExpr = astree.mk_global_variable_expr(
                 fnsymbol, globaladdress=int(str(tgtaddr.address), 16))
         else:
             (tgtxpr, _, _) = self.operands[0].ast_rvalue(astree)
     else:
         (tgtxpr, _, _) = self.operands[0].ast_rvalue(astree)
     call = astree.mk_call(lhs, tgtxpr, [])
     astree.add_instruction_span(call.id, iaddr, bytestring)
     return [call]
예제 #29
0
def xconstant_to_ast_expr(xc: X.XprConstant,
                          astree: AbstractSyntaxTree) -> AST.ASTExpr:
    """Convert a constant value to an AST Expr node."""

    if xc.is_int_constant:
        return astree.mk_integer_constant(xc.intvalue)

    else:
        raise UF.CHBError("AST conversion of xconstant " + str(xc) +
                          " not yet supported")
    def ast(self,
            astree: AbstractSyntaxTree,
            iaddr: str,
            bytestring: str,
            xdata: InstrXData) -> List[ASTInstruction]:
        lhs = xdata.vars[0]
        rhs1 = str(xdata.xprs[0])
        rhs2 = xdata.xprs[1]
        rhs3 = xdata.xprs[3]

        if lhs == "SP" and rhs1 == "SP" and rhs2.is_constant:
            return []

        lhsast = XU.xvariable_to_ast_lval(lhs, astree)
        if rhs1 == "SP" and rhs3.is_stack_address:
            rhs3 = cast("XprCompound", rhs3)
            stackoffset = rhs3.stack_address_offset()
            rhslval = astree.mk_stack_variable_lval(stackoffset)
            rhsast: ASTExpr = astree.mk_address_of(rhslval)

        elif rhs1 == "PC" or str(rhs2) == "PC":
            if rhs3.is_int_constant:
                rhsval = cast("XprConstant", rhs3).intvalue
                rhsast = astree.mk_integer_constant(rhsval)
            else:
                rhsast = XU.xxpr_to_ast_expr(rhs3, astree)

        else:
            rhsast = XU.xxpr_to_ast_expr(rhs3, astree)

        result = astree.mk_assign(lhsast, rhsast)
        astree.add_instruction_span(result.id, iaddr, bytestring)
        return [result]