void create_runtime_exception_block( DexString* except_str, std::vector<IRInstruction*>& block) { // new-instance v0, Ljava/lang/RuntimeException; // type@3852 // const-string v1, "Exception String e.g. Too many args" // string@7a6d // invoke-direct {v0, v1}, Ljava/lang/RuntimeException;.<init>:(Ljava/lang/String;)V // throw v0 auto new_inst = (new IRInstruction(OPCODE_NEW_INSTANCE)) ->set_type(DexType::make_type("Ljava/lang/RuntimeException;")); new_inst->set_dest(0); IRInstruction* const_inst = (new IRInstruction(OPCODE_CONST_STRING))->set_string(except_str); const_inst->set_dest(1); auto ret = DexType::make_type("V"); auto arg = DexType::make_type("Ljava/lang/String;"); auto args = DexTypeList::make_type_list({arg}); auto proto = DexProto::make_proto(ret, args); auto meth = DexMethod::make_method( DexType::make_type("Ljava/lang/RuntimeException;"), DexString::make_string("<init>"), proto); auto invk = new IRInstruction(OPCODE_INVOKE_DIRECT); invk->set_method(meth); invk->set_arg_word_count(2); invk->set_src(0, 0); invk->set_src(1, 1); IRInstruction* throwinst = new IRInstruction(OPCODE_THROW); block.emplace_back(new_inst); block.emplace_back(const_inst); block.emplace_back(invk); block.emplace_back(throwinst); }
void DexInstruction::verify_encoding() const { auto test = m_count ? new DexInstruction(opcode()) : new DexInstruction(opcode(), 0); if (dests_size()) { test->set_dest(dest()); } for (unsigned i = 0; i < srcs_size(); i++) { test->set_src(i, src(i)); } if (has_range_base()) test->set_range_base(range_base()); if (has_range_size()) test->set_range_size(range_size()); if (has_arg_word_count()) test->set_arg_word_count(arg_word_count()); if (has_literal()) test->set_literal(literal()); if (has_offset()) test->set_offset(offset()); assert_log(m_opcode == test->m_opcode, "%x %x\n", m_opcode, test->m_opcode); for (unsigned i = 0; i < m_count; i++) { assert_log(m_arg[i] == test->m_arg[i], "(%x %x) (%x %x)", m_opcode, m_arg[i], test->m_opcode, test->m_arg[i]); } delete test; }
void MethodBlock::new_array(DexType* type, const Location& size, const Location& dst) { auto insn = new IRInstruction(OPCODE_NEW_ARRAY); insn->set_type(type); insn->set_arg_word_count(1); insn->set_src(0, size.get_reg()); push_instruction(insn); push_instruction((new IRInstruction(IOPCODE_MOVE_RESULT_PSEUDO_OBJECT)) ->set_dest(dst.get_reg())); }
void MethodBlock::invoke(DexOpcode opcode, DexMethod* meth, std::vector<Location>& args) { always_assert(is_invoke(opcode)); auto invk = new DexOpcodeMethod(opcode, meth, 0); uint16_t arg_count = static_cast<uint16_t>(args.size()); invk->set_arg_word_count(arg_count); for (uint16_t i = 0; i < arg_count; i++) { auto arg = args[i]; invk->set_src(i, reg_num(arg)); } if (arg_count > mc->out_count) mc->out_count = arg_count; push_instruction(invk); }
void IRInstruction::normalize_registers() { if (is_invoke(opcode())) { auto& args = get_method()->get_proto()->get_args()->get_type_list(); size_t old_srcs_idx{0}; size_t srcs_idx{0}; if (m_opcode != OPCODE_INVOKE_STATIC) { ++srcs_idx; ++old_srcs_idx; } for (size_t args_idx = 0; args_idx < args.size(); ++args_idx) { always_assert_log( old_srcs_idx < srcs_size(), "Invalid arg indices in %s args_idx %d old_srcs_idx %d\n", SHOW(this), args_idx, old_srcs_idx); set_src(srcs_idx++, src(old_srcs_idx)); old_srcs_idx += is_wide_type(args.at(args_idx)) ? 2 : 1; } always_assert(old_srcs_idx == srcs_size()); set_arg_word_count(srcs_idx); } }