void change_visibility(DexMethod* method) { auto code = method->get_code(); always_assert(code != nullptr); editable_cfg_adapter::iterate(code, [](MethodItemEntry& mie) { auto insn = mie.insn; if (insn->has_field()) { auto cls = type_class(insn->get_field()->get_class()); if (cls != nullptr && !cls->is_external()) { set_public(cls); } auto field = resolve_field(insn->get_field(), is_sfield_op(insn->opcode()) ? FieldSearch::Static : FieldSearch::Instance); if (field != nullptr && field->is_concrete()) { set_public(field); set_public(type_class(field->get_class())); // FIXME no point in rewriting opcodes in the method insn->set_field(field); } } else if (insn->has_method()) { auto cls = type_class(insn->get_method()->get_class()); if (cls != nullptr && !cls->is_external()) { set_public(cls); } auto current_method = resolve_method( insn->get_method(), opcode_to_search(insn)); if (current_method != nullptr && current_method->is_concrete()) { set_public(current_method); set_public(type_class(current_method->get_class())); // FIXME no point in rewriting opcodes in the method insn->set_method(current_method); } } else if (insn->has_type()) { auto type = insn->get_type(); auto cls = type_class(type); if (cls != nullptr && !cls->is_external()) { set_public(cls); } } return editable_cfg_adapter::LOOP_CONTINUE; }); std::vector<DexType*> types; if (code->editable_cfg_built()) { code->cfg().gather_catch_types(types); } else { code->gather_catch_types(types); } for (auto type : types) { auto cls = type_class(type); if (cls != nullptr && !cls->is_external()) { set_public(cls); } } }
//--------------------------clone_shallow-------------------------------------- JVMState* JVMState::clone_shallow() const { JVMState* n = has_method() ? new JVMState(_method, _caller) : new JVMState(0); n->set_bci(_bci); n->set_locoff(_locoff); n->set_stkoff(_stkoff); n->set_monoff(_monoff); n->set_endoff(_endoff); n->set_sp(_sp); n->set_map(_map); return n; }
// The instruction format doesn't tell us the width of registers for invoke // so we inspect the signature of the method we're calling bool IRInstruction::invoke_src_is_wide(size_t i) const { always_assert(has_method()); // virtual methods have `this` as the 0th register argument, but the // arg list does NOT include `this` if (!is_invoke_static(m_opcode)) { if (i == 0) { // reference to `this`. References are never wide return false; } --i; } const std::deque<DexType*>& args = m_method->get_proto()->get_args()->get_type_list(); return is_wide_type(args[i]); }
uint64_t IRInstruction::hash() const { std::vector<uint64_t> bits; bits.push_back(opcode()); for (size_t i = 0; i < srcs_size(); i++) { bits.push_back(src(i)); } if (dests_size() > 0) { bits.push_back(dest()); } if (has_data()) { size_t size = get_data()->data_size(); const auto& data = get_data()->data(); for (size_t i = 0; i < size; i++) { bits.push_back(data[i]); } } if (has_type()) { bits.push_back(reinterpret_cast<uint64_t>(get_type())); } if (has_field()) { bits.push_back(reinterpret_cast<uint64_t>(get_field())); } if (has_method()) { bits.push_back(reinterpret_cast<uint64_t>(get_method())); } if (has_string()) { bits.push_back(reinterpret_cast<uint64_t>(get_string())); } if (has_literal()) { bits.push_back(get_literal()); } uint64_t result = 0; for (uint64_t elem : bits) { result ^= elem; } return result; }
MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const MethodDefinition &method_name, const Variant **p_defs, int p_defcount) { StringName mdname = method_name.name; #else MethodBind *ClassDB::bind_methodfi(uint32_t p_flags, MethodBind *p_bind, const char *method_name, const Variant **p_defs, int p_defcount) { StringName mdname = StaticCString::create(method_name); #endif OBJTYPE_WLOCK; ERR_FAIL_COND_V(!p_bind, NULL); p_bind->set_name(mdname); String instance_type = p_bind->get_instance_class(); #ifdef DEBUG_ENABLED if (has_method(instance_type, mdname)) { ERR_EXPLAIN("Class " + String(instance_type) + " already has a method " + String(mdname)); ERR_FAIL_V(NULL); } #endif ClassInfo *type = classes.getptr(instance_type); if (!type) { ERR_PRINTS("Couldn't bind method '" + mdname + "' for instance: " + instance_type); memdelete(p_bind); ERR_FAIL_V(NULL); } if (type->method_map.has(mdname)) { memdelete(p_bind); // overloading not supported ERR_EXPLAIN("Method already bound: " + instance_type + "::" + mdname); ERR_FAIL_V(NULL); } #ifdef DEBUG_METHODS_ENABLED if (method_name.args.size() > p_bind->get_argument_count()) { memdelete(p_bind); ERR_EXPLAIN("Method definition provides more arguments than the method actually has: " + instance_type + "::" + mdname); ERR_FAIL_V(NULL); } p_bind->set_argument_names(method_name.args); type->method_order.push_back(mdname); #endif type->method_map[mdname] = p_bind; Vector<Variant> defvals; defvals.resize(p_defcount); for (int i = 0; i < p_defcount; i++) { defvals.write[i] = *p_defs[p_defcount - i - 1]; } p_bind->set_default_arguments(defvals); p_bind->set_hint_flags(p_flags); return p_bind; }
ciMethod* method() const { assert(has_method(), ""); return _method; }