DexMethod* find_collision_excepting(const DexMethod* except, const DexString* name, const DexProto* proto, const DexClass* cls, bool is_virtual, bool check_direct) { for (auto& method : cls->get_dmethods()) { if (match(name, proto, method) && method != except) return method; } for (auto& method : cls->get_vmethods()) { if (match(name, proto, method) && method != except) return method; } if (!is_virtual) return nullptr; auto super = type_class(cls->get_super_class()); if (super) { auto method = resolve_virtual(super, name, proto); if (method && method != except) return method; } TypeVector children; get_all_children(cls->get_type(), children); for (const auto& child : children) { auto vmethod = check_vmethods(name, proto, child); if (vmethod && vmethod != except) return vmethod; if (check_direct) { auto dmethod = check_dmethods(name, proto, child); if (dmethod && dmethod != except) return dmethod; } } return nullptr; }
void RenameClassesPass::run_pass(DexStoresVector& stores, ConfigFiles& cfg, PassManager& mgr) { const JsonWrapper& json_cfg = cfg.get_json_config(); if (json_cfg.get("emit_name_based_locators", false)) { // TODO: Purge the old RenameClassesPass entirely everywhere. fprintf(stderr, "[RenameClassesPass] error: Configuration option " "emit_locator_strings is not compatible with RenameClassesPass. " "Upgrade to RenameClassesPassV2 instead.\n"); exit(EXIT_FAILURE); } auto scope = build_class_scope(stores); ClassHierarchy ch = build_type_hierarchy(scope); std::unordered_set<const DexType*> untouchables; for (const auto& base : m_untouchable_hierarchies) { auto base_type = DexType::get_type(base.c_str()); if (base_type != nullptr) { untouchables.insert(base_type); TypeSet children; get_all_children(ch, base_type, children); untouchables.insert(children.begin(), children.end()); } } mgr.incr_metric(METRIC_CLASSES_IN_SCOPE, scope.size()); rename_classes( scope, m_pre_filter_whitelist, m_post_filter_whitelist, untouchables, m_rename_annotations, mgr); TRACE(RENAME, 1, "renamed classes: %d anon classes, %d from single char patterns, " "%d from multi char patterns\n", match_inner, match_short, match_long); TRACE(RENAME, 1, "String savings, at least %d bytes \n", base_strings_size - ren_strings_size); }
void RenameClassesPass::run_pass(DexClassesVector& dexen, ConfigFiles& cfg) { auto scope = build_class_scope(dexen); std::unordered_set<const DexType*> untouchables; for (const auto& base : m_untouchable_hierarchies) { auto base_type = DexType::get_type(base.c_str()); if (base_type != nullptr) { untouchables.insert(base_type); TypeVector children; get_all_children(base_type, children); untouchables.insert(children.begin(), children.end()); } } rename_classes( scope, m_pre_filter_whitelist, m_post_filter_whitelist, m_path, untouchables, cfg.get_proguard_map(), m_rename_annotations); TRACE(RENAME, 1, "renamed classes: %d anon classes, %d from single char patterns, " "%d from multi char patterns\n", match_inner, match_short, match_long); TRACE(RENAME, 1, "String savings, at least %d bytes \n", base_strings_size - ren_strings_size); }
void search_hierarchy_for_matches(DexMethod* bridge, DexMethod* bridgee) { /* * Direct reference. The only one if it's non-virtual. */ auto clstype = bridgee->get_class(); auto name = bridgee->get_name(); auto proto = bridgee->get_proto(); TRACE(BRIDGE, 5, " %s %s %s\n", SHOW(clstype), SHOW(name), SHOW(proto)); m_potential_bridgee_refs.emplace(MethodRef(clstype, name, proto), bridge); if (!bridgee->is_virtual()) return; /* * Search super classes * * A bridge method in a derived class may be referred to using the name * of a super class if a method with a matching signature is defined in * that super class. * * To build the set of potential matches, we accumulate potential refs in * maybe_refs, and when we find a matching signature in a super class, we * add everything in maybe_refs to the set. */ std::vector<std::pair<MethodRef, DexMethod*>> maybe_refs; for (auto super = type_class(type_class(clstype)->get_super_class()); super != nullptr; super = type_class(super->get_super_class())) { maybe_refs.emplace_back( MethodRef(super->get_type(), name, proto), bridge); for (auto vmethod : super->get_vmethods()) { if (signature_matches(bridgee, vmethod)) { for (auto DEBUG_ONLY refp : maybe_refs) { TRACE(BRIDGE, 5, " %s %s %s\n", SHOW(std::get<0>(refp.first)), SHOW(std::get<1>(refp.first)), SHOW(std::get<2>(refp.first))); } m_potential_bridgee_refs.insert(maybe_refs.begin(), maybe_refs.end()); maybe_refs.clear(); } } } /* * Search sub classes * * Easy. Any subclass can refer to the bridgee. */ TypeVector subclasses; get_all_children(clstype, subclasses); for (auto subclass : subclasses) { m_potential_bridgee_refs.emplace(MethodRef(subclass, name, proto), bridge); TRACE(BRIDGE, 5, " %s %s %s\n", SHOW(subclass), SHOW(name), SHOW(proto)); } }