DexClass* create_merger_class(const DexType* type, const DexType* super_type, const std::vector<DexField*>& merger_fields, const TypeSet& interfaces, bool add_type_tag_field, bool with_default_ctor /* false */) { always_assert(type && super_type); std::vector<DexField*> fields; if (add_type_tag_field) { auto type_tag_field = static_cast<DexField*>(DexField::make_field( type, DexString::make_string(INTERNAL_TYPE_TAG_FIELD_NAME), get_int_type())); type_tag_field->make_concrete(ACC_PUBLIC | ACC_FINAL); fields.push_back(type_tag_field); } for (auto f : merger_fields) { fields.push_back(f); } // Put merger class in the same package as super_type. auto pkg_name = get_merger_package_name(super_type); auto cls = create_class(type, super_type, pkg_name, fields, interfaces, with_default_ctor); TRACE(TERA, 3, " created merger class w/ fields %s \n", SHOW(cls)); return cls; }
DexField* make_field_def(DexType* cls, const char* name, DexType* type, DexAccessFlags access = ACC_PUBLIC, bool external = false) { auto field = DexField::make_field(cls, DexString::make_string(name), type); if (external) { field->set_access(access); field->set_external(); } else { field->make_concrete(access); } return field; }
DexMethod* MethodCreator::make_static_from(DexString* name, DexProto* proto, DexMethod* meth, DexClass* target_cls) { assert(!(meth->get_access() & ACC_STATIC)); assert(!is_init(meth) && !is_clinit(meth)); auto smeth = DexMethod::make_method(target_cls->get_type(), name, proto); smeth->make_concrete( meth->get_access() | ACC_STATIC, std::move(meth->get_code()), false); target_cls->add_method(smeth); return smeth; }
DexMethod* MethodCreator::make_static_from(DexString* name, DexProto* proto, DexMethod* meth, DexClass* target_cls) { assert(!(meth->get_access() & ACC_STATIC)); assert(!is_init(meth) && !is_clinit(meth)); auto smeth = DexMethod::make_method(target_cls->get_type(), name, proto); smeth->make_concrete( meth->get_access() | ACC_STATIC, meth->get_code(), false); insert_sorted(target_cls->get_dmethods(), smeth, compare_dexmethods); meth->set_code(nullptr); return smeth; }
std::vector<DexField*> create_merger_fields( const DexType* owner, const std::vector<DexField*>& mergeable_fields) { std::vector<DexField*> res; size_t cnt = 0; for (const auto f : mergeable_fields) { auto type = f->get_type(); std::string name; if (type == get_byte_type() || type == get_char_type() || type == get_short_type() || type == get_int_type()) { type = get_int_type(); name = "i"; } else if (type == get_boolean_type()) { type = get_boolean_type(); name = "z"; } else if (type == get_long_type()) { type = get_long_type(); name = "j"; } else if (type == get_float_type()) { type = get_float_type(); name = "f"; } else if (type == get_double_type()) { type = get_double_type(); name = "d"; } else { static DexType* string_type = DexType::make_type("Ljava/lang/String;"); if (type == string_type) { type = string_type; name = "s"; } else { char t = type_shorty(type); always_assert(t == 'L' || t == '['); type = get_object_type(); name = "l"; } } name = name + std::to_string(cnt); auto field = static_cast<DexField*>( DexField::make_field(owner, DexString::make_string(name), type)); field->make_concrete(ACC_PUBLIC); res.push_back(field); cnt++; } TRACE(TERA, 8, " created merger fields %d \n", res.size()); return res; }