void Init_Class() { dummy_proc = rb_eval_string("$__loadso__dummy_proc = proc{}"); rb_mod_define_method = get_method(rb_cObject, "define_method"); rb_mod_public = get_method(rb_cObject, "public"); rb_mod_private = get_method(rb_cObject, "private"); rb_obj_singleton_class = get_global_func("singleton_class"); rb_obj_is_kind_of_ = get_global_func("kind_of?"); rb_mod_append_features = get_instance_method(rb_cModule, "append_features"); rb_mod_name = get_instance_method(rb_cModule, "name"); rb_mod_alias_method = get_instance_method(rb_cModule, "alias_method"); rb_class_new_instance_ = get_method(rb_cObject, "new"); obj_respond_to = get_global_func("respond_to?"); rb_obj_class_ = get_instance_method(rb_mKernel, "class"); rb_obj_clone_ = get_instance_method(rb_mKernel, "clone"); }
void remove_virtual_functionst::get_functions( const exprt &function, functionst &functions) { const irep_idt class_id=function.get(ID_C_class); const irep_idt component_name=function.get(ID_component_name); assert(!class_id.empty()); // iterate over all children, transitively std::vector<irep_idt> children= class_hierarchy.get_children_trans(class_id); for(const auto & child : children) { exprt method=get_method(child, component_name); if(method.is_not_nil()) { functiont function; function.class_id=child; function.symbol_expr=to_symbol_expr(method); function.symbol_expr.set(ID_C_class, child); functions.push_back(function); } } // Start from current class, go to parents until something // is found. irep_idt c=class_id; while(!c.empty()) { exprt method=get_method(c, component_name); if(method.is_not_nil()) { functiont function; function.class_id=c; function.symbol_expr=to_symbol_expr(method); function.symbol_expr.set(ID_C_class, c); functions.push_back(function); break; // abort } const class_hierarchyt::idst &parents= class_hierarchy.class_map[c].parents; if(parents.empty()) break; c=parents.front(); } }
TEST_F(PreVerify, InlineCallerTryCalleeIfThrows) { auto cls = find_class_named( classes, "Lcom/facebook/redexinline/InlineTest;"); auto m = find_vmethod_named(*cls, "testCallerTryCalleeIfThrows"); auto invoke = find_invoke(m, OPCODE_INVOKE_DIRECT, "throwsInIf"); ASSERT_NE(nullptr, invoke); // verify that the callee has an if-else statement, and that the if block // (which throws an exception) comes before the return opcode auto callee_insns = invoke->get_method()->get_code()->get_instructions(); auto ifop = std::find_if(callee_insns.begin(), callee_insns.end(), [](DexInstruction* insn) { return insn->opcode() == OPCODE_IF_NEZ; }); ASSERT_NE(callee_insns.end(), ifop); auto retop = std::find_if(callee_insns.begin(), callee_insns.end(), [](DexInstruction* insn) { return insn->opcode() == OPCODE_RETURN_VOID; }); ASSERT_NE(callee_insns.end(), retop); auto invoke_throw = find_invoke(ifop, retop, OPCODE_INVOKE_VIRTUAL, "wrapsThrow"); ASSERT_NE(nullptr, invoke_throw); auto& code = m->get_code(); ASSERT_EQ(code->get_tries().size(), 1); }
int allium_ptcfg_bind_addr(const allium_ptcfg *cfg, const char *method, struct sockaddr *addr, socklen_t *addr_len) { struct allium_ptcfg_method_s *m; if ((NULL == cfg) || (NULL == method) || (NULL == addr_len)) return (ALLIUM_ERR_INVAL); if (!cfg->is_server) return (ALLIUM_ERR_PTCFG_NOT_SERVER); m = get_method(cfg, method); if (NULL == m) return (ALLIUM_ERR_PTCFG_INVALID_METHOD); if ((NULL == addr) || (*addr_len < m->bind_addr_len)) { *addr_len = m->bind_addr_len; return (ALLIUM_ERR_NOBUFS); } if (!m->has_bind_addr) { *addr_len = 0; return (ALLIUM_ERR_PTCFG_NO_ADDRESS); } memcpy(addr, &m->bind_addr, m->bind_addr_len); *addr_len = m->bind_addr_len; return (0); }
size_t delete_methods( std::vector<DexClass*>& scope, std::unordered_set<DexMethod*>& removable, std::function<DexMethod*(DexMethod*, MethodSearch search)> resolver) { // if a removable candidate is invoked do not delete walk_opcodes(scope, [](DexMethod* meth) { return true; }, [&](DexMethod* meth, DexInstruction* insn) { if (is_invoke(insn->opcode())) { const auto mop = static_cast<DexOpcodeMethod*>(insn); auto callee = resolver(mop->get_method(), opcode_to_search(insn)); if (callee != nullptr) { removable.erase(callee); } } }); size_t deleted = 0; for (auto callee : removable) { if (!callee->is_concrete()) continue; if (do_not_strip(callee)) continue; auto cls = type_class(callee->get_class()); always_assert_log(cls != nullptr, "%s is concrete but does not have a DexClass\n", SHOW(callee)); if (callee->is_virtual()) { cls->get_vmethods().remove(callee); } else { cls->get_dmethods().remove(callee); } deleted++; TRACE(DELMET, 4, "removing %s\n", SHOW(callee)); } return deleted; }
int allium_ptcfg_method_requested(const allium_ptcfg *cfg, const char *method) { if ((NULL == cfg) || (NULL == method)) return (ALLIUM_ERR_INVAL); return (NULL != get_method(cfg, method)); }
Method* Profiler::enter_method(Env* env, robject recv, rsymbol name, rmodule mod, rmethod cm) { if(env->module_is_metaclass(mod)) { robject attached = env->metaclass_attached_instance(mod); rmodule as_module = env->cast_to_rmodule(attached); if(as_module) { return get_method(env, cm, name, env->module_name(as_module), kSingleton); } else { rstring str = env->to_s(mod); return get_method(env, cm, name, env->string_to_symbol(str), kSingleton); } } else { return get_method(env, cm, name, env->module_name(mod), kNormal); } }
static void init_qtree(DATA *d) { /* * Initialize the root of the search tree: * Since this is called from qtree_quick_select(), we know allready * quite a lot. This helps choosing sensible values for the * top level bbox origin and size. */ const GRIDMAP *gt = NULL; DATA *simlocs = NULL; int i, mode; BBOX bbox; if (is_simulation(get_method())) { /* * sequential simulation: the simulation path (through DATA or GRIDMAP) * will make up for (most of) the search locations: */ gt = (const GRIDMAP *) NULL; simlocs = get_dataval(); /* in case of simulation one of them will be non-NULL */ } /* get initial estimate for top level bbox: */ if (gt != NULL) bbox = bbox_from_grid(gt, NULL); else if (simlocs != NULL) { bbox = bbox_from_data(simlocs); if (bbox.size <= 0.0) bbox = bbox_from_data(d); } else bbox = bbox_from_data(d); if (bbox.size <= 0.0) bbox = bbox_from_data(get_dataval()); if (bbox.size <= 0.0) ErrMsg(ER_IMPOSVAL, "bbox with zero size: remove neighbourhood settings?"); init_qnode(&(d->qtree_root), d->n_list < gl_split, bbox); /* ML1 */ mode = bbox.mode; for (i = 0; i < d->n_list; i++) qtree_push_point(d, d->list[i]); /* now they won't be rejected */ /* ML2 */ if (DEBUG_DUMP) { printlog("top level search tree statistics for data(%s):\n", name_identifier(d->id)); printlog("bounding box origin ["); if (mode & X_BIT_SET) printlog("%g", d->qtree_root->bb.x); if (mode & Y_BIT_SET) printlog(",%g", d->qtree_root->bb.y); if (mode & Z_BIT_SET) printlog(",%g", d->qtree_root->bb.z); printlog("]; dimension %g\n", d->qtree_root->bb.size); } /* qtree_print(d); */ return; }
VALUE *VALUE::send(char *method, int argc, VALUE *argv) { rd_method *meth = get_method(method); if(meth) { return meth->perform(argc, argv, argv); } printf("Undefined variable or method: `%s' for :%s (NameError)\n", method, name); exit(1); }
GDMonoMethod *GDMonoClass::get_method(MonoMethod *p_raw_method) { MonoMethodSignature *sig = mono_method_signature(p_raw_method); int params_count = mono_signature_get_param_count(sig); StringName method_name = mono_method_get_name(p_raw_method); return get_method(p_raw_method, method_name, params_count); }
void spec_uncompress(int in, int out, int lev) { level=lev; part_nb=0; clear_bufs(); ifd=in; ofd=out; method = get_method(1); unzip(ifd,ofd); }
/* function returns method of given name or NULL if not found */ const struct method *get_interface_method(const char *iname, const char *mname) { const struct interface *iface = get_interface(iname); if (iface == NULL) return NULL; return get_method(iface->methods, mname); }
GDMonoMethod *GDMonoClass::get_method_with_desc(const String &p_description, bool p_include_namespace) { MonoMethodDesc *desc = mono_method_desc_new(p_description.utf8().get_data(), p_include_namespace); MonoMethod *method = mono_method_desc_search_in_class(desc, mono_class); mono_method_desc_free(desc); ERR_FAIL_COND_V(mono_method_get_class(method) != mono_class, NULL); return get_method(method); }
static SCM api_get_method(SCM s_) { servlet *s = scm_to_pointer(s_); const char *method = get_method(s); if (method) { return scm_from_utf8_string(method); } return SCM_UNSPECIFIED; }
TEST_F(PreVerify, InlineInvokeDirect) { auto cls = find_class_named( classes, "Lcom/facebook/redexinline/InlineTest;"); auto m = find_vmethod_named(*cls, "testInlineInvokeDirect"); auto invoke = find_invoke(m, OPCODE_INVOKE_DIRECT, "hasNoninlinableInvokeDirect"); auto noninlinable_invoke_direct = find_invoke(invoke->get_method(), OPCODE_INVOKE_DIRECT, "noninlinable"); auto noninlinable = noninlinable_invoke_direct->get_method(); ASSERT_EQ(show(noninlinable->get_proto()), "()V"); // verify that there are two inlinable() methods in the class. The static // version exists to test that we don't cause a signature collision when we // make the instance method static. auto dmethods = cls->get_dmethods(); ASSERT_EQ(2, std::count_if(dmethods.begin(), dmethods.end(), [](DexMethod* m) { return !strcmp("noninlinable", m->get_name()->c_str()); })); }
static jobject get_module_loader(JNIEnv *env, jobject module) { static jmethodID cl_method = NULL; jobject loader = NULL; if (cl_method == NULL) { cl_method = get_method(env, jlrM(env), "getClassLoader", "()Ljava/lang/ClassLoader;"); } loader = (jobject)JNI_ENV_PTR(env)->CallObjectMethod(JNI_ENV_ARG(env, module), cl_method); return loader; }
steering_vector* create_steering_vector(std::string steering_string) { steering_vector* sv = NULL; // check whether a steering vector is to be used and set up the class if it is std::string steering = get_method(steering_string); // determine which (inherited) steering class to use if (steering == "geostrophic") sv = new geo_wind_vector(); else if (steering != "") throw (std::string("Unknown steering vector method: " + steering)); // note - this function can return NULL if the steering string is empty return sv; }
void analyze_invoke(cfg::InstructionIterator it, Environment* env) { auto insn = it->insn; DexMethodRef* ref = insn->get_method(); if (ref->get_name()->str() == "ordinal") { // All methods named `ordinal` is overly broad, but we throw out false // positives later Info info; info.invoke = it; env->set(RESULT_REGISTER, Domain(info)); } else { analyze_default(it, env); } }
void MultiMethodInliner::inline_callees( InlineContext& inline_context, std::vector<DexMethod*>& callees) { size_t found = 0; auto caller = inline_context.caller; auto insns = caller->get_code()->get_instructions(); // walk the caller opcodes collecting all candidates to inline // Build a callee to opcode map std::vector<std::pair<DexMethod*, DexOpcodeMethod*>> inlinables; for (auto insn = insns.begin(); insn != insns.end(); ++insn) { if (!is_invoke((*insn)->opcode())) continue; auto mop = static_cast<DexOpcodeMethod*>(*insn); auto callee = resolver(mop->get_method(), opcode_to_search(*insn)); if (callee == nullptr) continue; if (std::find(callees.begin(), callees.end(), callee) == callees.end()) { continue; } always_assert(callee->is_concrete()); found++; inlinables.push_back(std::make_pair(callee, mop)); if (found == callees.size()) break; } if (found != callees.size()) { always_assert(found <= callees.size()); info.not_found += callees.size() - found; } // attempt to inline all inlinable candidates for (auto inlinable : inlinables) { auto callee = inlinable.first; auto mop = inlinable.second; if (!is_inlinable(callee, caller)) continue; auto op = mop->opcode(); if (is_invoke_range(op)) { info.invoke_range++; continue; } TRACE(MMINL, 4, "inline %s (%d) in %s (%d)\n", SHOW(callee), caller->get_code()->get_registers_size(), SHOW(caller), callee->get_code()->get_registers_size() - callee->get_code()->get_ins_size()); change_visibility(callee); MethodTransform::inline_16regs(inline_context, callee, mop); info.calls_inlined++; inlined.insert(callee); } }
void remove_virtual_functionst::get_functions( const exprt &function, functionst &functions) { const irep_idt class_id=function.get(ID_C_class); const irep_idt component_name=function.get(ID_component_name); assert(!class_id.empty()); functiont root_function; // Start from current class, go to parents until something // is found. irep_idt c=class_id; while(!c.empty()) { exprt method=get_method(c, component_name); if(method.is_not_nil()) { root_function.class_id=c; root_function.symbol_expr=to_symbol_expr(method); root_function.symbol_expr.set(ID_C_class, c); break; // abort } const class_hierarchyt::idst &parents= class_hierarchy.class_map[c].parents; if(parents.empty()) break; c=parents.front(); } if(root_function.class_id.empty()) { // No definition here; this is an abstract function. root_function.class_id=class_id; } // iterate over all children, transitively std::set<irep_idt> visited; get_child_functions_rec( class_id, root_function.symbol_expr, component_name, functions, visited); if(root_function.symbol_expr!=symbol_exprt()) functions.push_back(root_function); }
// Check that visibility / accessibility changes to the current method // won't need to change a referenced method into a virtual or static one. bool gather_invoked_methods_that_prevent_relocation( const DexMethod* method, std::unordered_set<DexMethodRef*>* methods_preventing_relocation) { auto code = method->get_code(); always_assert(code); bool can_relocate = true; for (const auto& mie : InstructionIterable(code)) { auto insn = mie.insn; auto opcode = insn->opcode(); if (is_invoke(opcode)) { auto meth = resolve_method(insn->get_method(), opcode_to_search(insn)); if (!meth && opcode == OPCODE_INVOKE_VIRTUAL && unknown_virtuals::is_method_known_to_be_public(insn->get_method())) { continue; } if (meth) { always_assert(meth->is_def()); if (meth->is_external() && !is_public(meth)) { meth = nullptr; } else if (opcode == OPCODE_INVOKE_DIRECT && !is_init(meth)) { meth = nullptr; } } if (!meth) { can_relocate = false; if (!methods_preventing_relocation) { break; } methods_preventing_relocation->emplace(insn->get_method()); } } } return can_relocate; }
jv_method *get_method(java_lang_Class *cls, const utf8_const *name, const utf8_const *signature) { for (int16_t m = 0, n = cls->method_count; m < n; ++m) { jv_method *method = &cls->me.methods[m]; if (utf8_consts_equal(method->name, name) && utf8_consts_equal(method->signature, signature)) return method; } java_lang_Class *superclass = cls->superclass; if (superclass != NULL) return get_method(superclass, name, signature); else return NULL; }
NativeMethod* NativeInitializer::newNativeMethod(uint32_t i) const { const NativeMethodInfo* ni = get_method(i); if (!ni) return NULL; NativeMethod* info = new (core->GetGC()) NativeMethod(ni->thunker, ni->handler); info->flags |= AbstractFunction::ABSTRACT_METHOD; #ifdef AVMPLUS_LEGACY_NATIVE_MAPS info->flags |= ni->flags; info->cookie = ni->cookie; #else info->flags |= AbstractFunction::NEEDS_CODECONTEXT | AbstractFunction::NEEDS_DXNS; #endif return info; }
/** * Ensure the structures in DelSuperTest.java are as expected * following a redex transformation. */ TEST_F(PostVerify, DelSuper) { std::cout << "Loaded classes: " << classes.size() << std::endl ; // Should have C1 and 2 C2 still auto c1 = find_class_named( classes, "Lcom/facebook/redex/test/instr/DelSuperTest$C1;"); ASSERT_NE(nullptr, c1); auto c2 = find_class_named( classes, "Lcom/facebook/redex/test/instr/DelSuperTest$C2;"); ASSERT_NE(nullptr, c2); // C2.optimized1 and C2.optimized2 should be gone // XXX: optimized2() doesn't get delsuper treatment due to inlining of C1.optimize2(?) auto&& m2 = !m::any_vmethods( m::named<DexMethod>("optimized1")/* || m::named<DexMethod>("optimized2")*/); ASSERT_TRUE(m2.matches(c2)); // C1 and C2 should both have 4 notOptimized* methods auto&& m3 = m::any_vmethods(m::named<DexMethod>("notOptimized1")) && m::any_vmethods(m::named<DexMethod>("notOptimized2")) && m::any_vmethods(m::named<DexMethod>("notOptimized3")) && m::any_vmethods(m::named<DexMethod>("notOptimized4")); ASSERT_TRUE(m3.matches(c1)); ASSERT_TRUE(m3.matches(c2)); // check that the invoke instructions are fixed up as well auto test_class = find_class_named( classes, "Lcom/facebook/redex/test/instr/DelSuperTest;"); auto test_opt_1 = find_vmethod_named(*test_class, "testOptimized1"); int optimized1_count = 0; for (auto& insn : test_opt_1->get_code()->get_instructions()) { if (is_invoke(insn->opcode())) { auto mop = static_cast<DexOpcodeMethod*>(insn); auto m = mop->get_method(); if (strcmp(m->get_name()->c_str(), "optimized1") == 0) { ASSERT_STREQ(m->get_class()->get_name()->c_str(), "Lcom/facebook/redex/test/instr/DelSuperTest$C1;"); ++optimized1_count; } } } ASSERT_EQ(optimized1_count, 3); }
extrema_locator* create_extrema_locator(std::string method_string) { extrema_locator* el; std::string method = get_method(method_string); // determine which class to use to do the extrema location if (method=="minima") el = new minima_locator(); else if (method=="maxima") el = new maxima_locator(); else if (method=="minima_back") // minima with background removal el = new minima_background(); else if (method=="minima_back_wind") el = new minima_back_wind(); else throw (std::string("Unsupported extrema location method: " + method)); return el; }
int parse_header(ci_request_t * req) { int i, request_status = 0, result; ci_headers_list_t *h; h = req->request_header; if ((request_status = ci_read_icap_header(req, h, TIMEOUT)) < 0) return request_status; if ((result = get_method(h->buf)) >= 0) { req->type = result; if ((request_status = parse_request(req, h->buf)) != EC_100) return request_status; } else return EC_400; if ((request_status = ci_headers_unpack(h)) != EC_100) return request_status; for (i = 1; i < h->used; i++) { if (strncasecmp("Preview:", h->headers[i], 8) == 0) { result = strtol(h->headers[i] + 9, NULL, 10); if (errno != EINVAL && errno != ERANGE) { req->preview = result; if (result >= 0) ci_buf_reset_size(&(req->preview_data), result + 64); } } else if (strncasecmp("Encapsulated: ", h->headers[i], 14) == 0) request_status = process_encapsulated(req, h->headers[i]); else if (strncasecmp("Connection: ", h->headers[i], 12) == 0) { /* if(strncasecmp(h->headers[i]+12,"keep-alive",10)==0)*/ if (strncasecmp(h->headers[i] + 12, "close", 5) == 0) req->keepalive = 0; /*else the default behaviour of keepalive ..... */ } else if (strncasecmp("Allow: 204", h->headers[i], 10) == 0) { req->allow204 = 1; } } return request_status; }
/* * procedure map_sign() for putting history and description to maps (csf) * history is fixed for a session; description depends on the map contents */ void map_sign(GRIDMAP *m, const char *what) { char *pwd = NULL, *user = NULL, *timestring = NULL, *fname = NULL; time_t tm; if ((user = getenv("LOGNAME")) == NULL) user = ""; if ((pwd = getenv("PWD")) == NULL) pwd = ""; if ((fname = command_file_name) == NULL) fname = ""; tm = time(&tm); if ((timestring = asctime(localtime(&tm))) == NULL) timestring = ""; m->history = (char *) emalloc(1024 * sizeof(char)); #ifdef HAVE_SNPRINTF snprintf #else sprintf #endif (m->history, #ifdef HAVE_SNPRINTF 1024, #endif "%s%s\n%s %s %s\n%s%s\n%s %s\n%s %s\n%s %s (seed %lu)\n", *user ? "creator: " : "", user, "program: ", argv0, VERSION, *pwd ? "path: " : "", pwd, "command file: ", fname, "method used: ", method_string(get_method()), "date: ", timestring, get_seed()); if (what == NULL) { /* paranoia */ m->description = (char *) emalloc(sizeof(char)); m->description[0] = '\0'; } else { m->description = (char *) emalloc((strlen(what) + 1) * sizeof(char)); #ifdef HAVE_SNPRINTF snprintf(m->description, strlen(what) + 1, "%s\n", what); #else sprintf(m->description, "%s\n", what); #endif } }
TEST_F(PreVerify, testArrayDataInCaller) { auto cls = find_class_named( classes, "Lcom/facebook/redexinline/InlineTest;"); auto m = find_vmethod_named(*cls, "testArrayDataInCaller"); // check that the callee indeed has a non-terminal if, which will exercise // the inliner code path that searches for fopcodes in the caller auto callee = find_invoke(m, OPCODE_INVOKE_DIRECT, "calleeWithIf"); auto insns = callee->get_method()->get_code()->get_instructions(); auto ret_it = std::find_if(insns.begin(), insns.end(), [&](DexInstruction* insn) { return is_return(insn->opcode()); }); ASSERT_NE(ret_it, insns.end()); auto last_insn = m->get_code()->get_instructions().back(); ASSERT_EQ(last_insn->opcode(), FOPCODE_FILLED_ARRAY); }
/** * If the caller is in the primary DEX we want to make sure there are no * references in other DEXes that may cause a verification error. * Don't inline if so. */ bool MultiMethodInliner::refs_not_in_primary(DexMethod* callee) { const auto ok_from_primary = [&](DexType* type) { if (primary.count(type) == 0 && type_class_internal(type) != nullptr) { info.not_in_primary++; return false; } return true; }; for (auto insn : callee->get_code()->get_instructions()) { if (insn->has_types()) { auto top = static_cast<DexOpcodeType*>(insn); if (!ok_from_primary(top->get_type())) { return true; } } else if (insn->has_methods()) { auto mop = static_cast<DexOpcodeMethod*>(insn); auto meth = mop->get_method(); if (!ok_from_primary(meth->get_class())) { return true; } auto proto = meth->get_proto(); if (!ok_from_primary(proto->get_rtype())) { return true; } auto args = proto->get_args(); if (args == nullptr) continue; for (const auto& arg : args->get_type_list()) { if (!ok_from_primary(arg)) { return true; } } } else if (insn->has_fields()) { auto fop = static_cast<DexOpcodeField*>(insn); auto field = fop->field(); if (!ok_from_primary(field->get_class()) || !ok_from_primary(field->get_type())) { return true; } } } return false; }
/** * Change the visibility of members accessed in a callee as they are moved * to the caller context. * We make everything public but we could be more precise and only * relax visibility as needed. */ void MultiMethodInliner::change_visibility(DexMethod* callee) { TRACE(MMINL, 6, "checking visibility usage of members in %s\n", SHOW(callee)); for (auto insn : callee->get_code()->get_instructions()) { if (insn->has_fields()) { auto fop = static_cast<DexOpcodeField*>(insn); auto field = fop->field(); field = resolve_field(field, is_sfield_op(insn->opcode()) ? FieldSearch::Static : FieldSearch::Instance); if (field != nullptr && field->is_concrete()) { TRACE(MMINL, 6, "changing visibility of %s.%s %s\n", SHOW(field->get_class()), SHOW(field->get_name()), SHOW(field->get_type())); set_public(field); set_public(type_class(field->get_class())); fop->rewrite_field(field); } continue; } if (insn->has_methods()) { auto mop = static_cast<DexOpcodeMethod*>(insn); auto method = mop->get_method(); method = resolver(method, opcode_to_search(insn)); if (method != nullptr && method->is_concrete()) { TRACE(MMINL, 6, "changing visibility of %s.%s: %s\n", SHOW(method->get_class()), SHOW(method->get_name()), SHOW(method->get_proto())); set_public(method); set_public(type_class(method->get_class())); mop->rewrite_method(method); } continue; } if (insn->has_types()) { auto type = static_cast<DexOpcodeType*>(insn)->get_type(); auto cls = type_class(type); if (cls != nullptr && !cls->is_external()) { TRACE(MMINL, 6, "changing visibility of %s\n", SHOW(type)); set_public(cls); } continue; } } }