def arguments(self, xdata: InstrXData) -> List[XXpr]: if xdata.has_indirect_call_target_exprs(): return xdata.xprs[2:] elif xdata.has_call_target(): return xdata.xprs else: return []
def annotation(self, xdata: InstrXData) -> str: args = ", ".join(str(x) for x in self.arguments(xdata)) if xdata.has_call_target(): return "call " + str(xdata.call_target( self.ixd)) + "(" + args + ")" else: return "call- " + str(self.target) + "(" + args + ")"
def call_target(self, xdata: InstrXData) -> "CallTarget": if xdata.has_call_target(): return xdata.call_target(self.ixd) else: raise UF.CHBError( "Syscall instruction does not have a call target: " + str(self))
def annotation(self, xdata: InstrXData) -> str: """data formats: call, jumptable, indirect jump call: [a:..., 'call'], <args> + <index of call-target in ixd> jumptable: [a:x, 'table'], [xpr, [< i, address index>]] indirect jump: [a:x], [ xpr ] """ if self.is_call(xdata) and xdata.has_call_target(): tgt = xdata.call_target(self.ixd) args = ", ".join(str(x) for x in self.arguments(xdata)) return "call " + str(tgt) + "(" + args + ")" elif self.is_jump_table(xdata): tgtd = get_jump_table_targets([str(i) for i in xdata.args[1:]]) tgtstr = ' (' for t in sorted(tgtd): tgtaddr = self.mipsd.app.bdictionary.address(int(t)) tgtstr += (str(tgtd[t]) + ':' + str(tgtaddr) + ',') tgtstr += ')' jtgts = tgtstr else: jtgts = '' tgtx = str(xdata.xprs[0]) return 'jmp* ' + tgtx + ' ' + jtgts + ' (' + str( self.src_operand) + ')'
def annotation(self, xdata: InstrXData) -> str: if self.is_call(xdata) and xdata.has_call_target(): tgt = xdata.call_target(self.ixd) args = ", ".join(str(x) for x in self.arguments(xdata)) return "call " + str(tgt) + "(" + args + ")" else: return 'goto ' + str(self.target)
def annotation(self, xdata: InstrXData) -> str: if xdata.has_call_target(): args = ", ".join(str(x) for x in xdata.xprs) tgt = str(self.call_target(xdata)) return "call " + tgt + "(" + args + ")" else: tgtx = str(xdata.xprs[0]) return 'call* ' + tgtx
def ast(self, astree: AbstractSyntaxTree, iaddr: str, bytestring: str, xdata: InstrXData) -> List[ASTInstruction]: if self.is_call(xdata) and xdata.has_call_target(): calltarget = xdata.call_target(self.ixd) tgtname = calltarget.name tgtxpr = self.target_expr_ast(astree, xdata) (lhs, assigns) = self.lhs_ast(astree, iaddr, xdata) args = self.arguments(xdata) argregs = ["R0", "R1", "R2", "R3"] callargs = argregs[:len(args)] argxprs: List[ASTExpr] = [] for (reg, arg) in zip(callargs, args): if XU.is_struct_field_address(arg, astree): addr = XU.xxpr_to_struct_field_address_expr(arg, astree) argxprs.append(addr) elif arg.is_string_reference: regast = astree.mk_register_variable_expr(reg) cstr = arg.constant.string_reference() saddr = hex(arg.constant.value) argxprs.append(astree.mk_string_constant(regast, cstr, saddr)) elif arg.is_argument_value: argindex = arg.argument_index() funarg = astree.function_argument(argindex) if funarg: astxpr = astree.mk_register_variable_expr( funarg.name, vtype=funarg.typ, parameter=argindex) argxprs.append(astxpr) else: argxprs.append(astree.mk_register_variable_expr(reg)) else: argxprs.append(astree.mk_register_variable_expr(reg)) if len(args) > 4: for a in args[4:]: argxprs.append(XU.xxpr_to_ast_expr(a, astree)) if lhs.is_ignored: call: ASTInstruction = astree.mk_call(lhs, tgtxpr, argxprs) astree.add_instruction_span(call.id, iaddr, bytestring) return [call] else: call = cast(ASTInstruction, astree.mk_call(lhs, tgtxpr, argxprs)) astree.add_instruction_span(call.id, iaddr, bytestring) for assign in assigns: astree.add_instruction_span(assign.id, iaddr, bytestring) return [call] + assigns else: return self.assembly_ast(astree, iaddr, bytestring, xdata)
def ast(self, astree: AbstractSyntaxTree, iaddr: str, bytestring: str, xdata: InstrXData) -> List[ASTInstruction]: tgtx = str(xdata.xprs[0]) if tgtx == "$ra_in": return [] elif self.is_call(xdata) and xdata.has_call_target(): calltarget = xdata.call_target(self.ixd) tgtname = calltarget.name tgtxpr = self.target_expr_ast(astree, xdata) (lhs, assigns) = self.lhs_ast(astree, iaddr, xdata) args = self.arguments(xdata) argxprs: List[ASTExpr] = [] for arg in args: if XU.is_struct_field_address(arg, astree): addr = XU.xxpr_to_struct_field_address_expr(arg, astree) elif arg.is_string_reference: xpr = XU.xxpr_to_ast_expr(arg, astree) cstr = arg.constant.string_reference() saddr = hex(arg.constant.value) argxprs.append(astree.mk_string_constant(xpr, cstr, saddr)) elif arg.is_argument_value: argindex = arg.argument_index() funarg = astree.function_argument(argindex) if funarg: astxpr = astree.mk_register_variable_expr( funarg.name, vtype=funarg.typ, parameter=argindex) argxprs.append(astxpr) else: astxpr = XU.xxpr_to_ast_expr(arg, astree) argxprs.append(astxpr) else: astxpr = XU.xxpr_to_ast_expr(arg, astree) argxprs.append(astxpr) if lhs.is_ignored: call: ASTInstruction = astree.mk_call(lhs, tgtxpr, argxprs) astree.add_instruction_span(call.id, iaddr, bytestring) return [call] else: call = cast(ASTInstruction, astree.mk_call(lhs, tgtxpr, argxprs)) astree.add_instruction_span(call.id, iaddr, bytestring) for assign in assigns: astree.add_instruction_span(assign.id, iaddr, bytestring) return [call] + assigns else: # TODO: accomodate indirect jumps return []
def annotation(self, xdata: InstrXData) -> str: """xdata format: a:x . xprs[0]: target operand """ if self.is_call(xdata) and xdata.has_call_target(): tgt = xdata.call_target(self.ixd) args = ", ".join(str(x) for x in self.arguments(xdata)) return "call " + str(tgt) + "(" + args + ")" else: ctgt = str(xdata.xprs[0]) args = ", ".join(str(xdata.xprs[i]) for i in [1, 2, 3, 4]) return "call " + ctgt + "(" + args + ")"
def annotation(self, xdata: InstrXData) -> str: """data formats: call, jumptable, indirect jump call: [a:..., 'call'], <args> + <index of call-target in ixd> or xdata format: a:x . xprs[0]: target operand """ if self.is_call(xdata) and xdata.has_call_target(): tgt = xdata.call_target(self.ixd) args = ", ".join(str(x) for x in self.arguments(xdata)) return "call " + str(tgt) + "(" + args + ")" ctgt = str(xdata.xprs[0]) return "call " + ctgt
def annotation(self, xdata: InstrXData) -> str: """data format: a:<v0><args><call-target-ix> , or a:<v0> xprs[0]: value of v0 xprs[1...]: arguments xprs[-1]: index of call target in interface dictionary """ if xdata.has_call_target(): pargs = "(" + ", ".join(str(a) for a in self.arguments(xdata)) + ")" return str(xdata.call_target(self.ixd)) + pargs else: rhs = str(xdata.xprs[0]) if rhs.startswith("0x"): syscallnumber = int(rhs, 16) syscallfunction = SC.get_mips_linux_syscall(syscallnumber) return "linux-systemcall:" + syscallfunction else: return "linux-systemcall(" + rhs + ")"
def assembly_ast(self, astree: AbstractSyntaxTree, iaddr: str, bytestring: str, xdata: InstrXData) -> List[ASTInstruction]: if self.is_call_instruction(xdata) and xdata.has_call_target(): 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=tgtaddr.address.get_int()) 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] else: return []
def annotation(self, xdata: InstrXData) -> str: """data format: a:xx... + c direct call / resolved indirect call: xprs[0..] arguments calltarget unresolved indirect call: xprs[0] target expression xprs[1] target expression (simplified) xprs[2...] arguments """ if xdata.has_indirect_call_target_exprs(): tgtx = xdata.xprs[1] callargs = xdata.xprs[2:] return str(tgtx) + "(" + ",".join([str(x) for x in callargs]) + ")" elif xdata.has_call_target(): ctgt = xdata.call_target(self.ixd) callargs = xdata.xprs return str(ctgt) + "(" + ",".join([str(x) for x in callargs]) + ")" else: return "call to " + str(self.tgtoperand)
def call_target(self, xdata: InstrXData) -> "CallTarget": if xdata.has_call_target(): return xdata.call_target(self.ixd) else: raise UF.CHBError("Instruction is not a call: " + str(self))
def has_call_target(self, xdata: InstrXData) -> bool: return xdata.has_call_target()
def has_call_target(self, xdata: InstrXData) -> bool: """Returns true if this is a direct call or a resolved indirect call.""" return xdata.has_call_target()
def call_target(self, xdata: InstrXData) -> "CallTarget": if xdata.has_call_target(): return xdata.call_target(self.ixd) else: raise UF.CHBError("Call target not found for " + str(self))
def is_call_instruction(self, xdata: InstrXData) -> bool: return xdata.has_call_target()