void unmark_keep(const Scope& scope, const std::vector<std::string>& package_list, const std::vector<std::string>& supercls_list) { if (package_list.size() == 0 && supercls_list.size() == 0) { return; } std::unordered_set<const DexType*> superclasses; std::unordered_set<const DexType*> interface_list; for (auto& cls_name : supercls_list) { const DexType* supercls_type = DexType::get_type(cls_name); if (supercls_type) { DexClass* supercls = type_class(supercls_type); if (supercls && is_interface(supercls)) { interface_list.emplace(supercls_type); } else { superclasses.emplace(supercls_type); } } } TypeSystem ts(scope); // Unmark proguard keep rule for interface implementors like // "-keep class * extend xxx". for (const DexType* intf_type : interface_list) { for (const DexType* implementor : ts.get_implementors(intf_type)) { DexClass* implementor_cls = type_class(implementor); if (implementor_cls) { implementor_cls->rstate.force_unset_allowshrinking(); } } } walk::parallel::classes( scope, [&ts, &superclasses, &package_list](DexClass* cls) { // Unmark proguard keep rule for classes under path from package list. for (const auto& package : package_list) { if (strstr(cls->get_name()->c_str(), package.c_str()) != nullptr) { cls->rstate.force_unset_allowshrinking(); return; } } if (!is_interface(cls)) { // Unmark proguard keep for classes that extend class from superclass // list for proguard keep rule like "-keep class * extend xxx". const auto& parents_chain = ts.parent_chain(cls->get_type()); if (parents_chain.size() <= 2) { // The class's direct super class is java.lang.Object, no need // to proceed. return; } // We only need to find class started at the second of parents_chain // because first is java.lang.Object, and end at second to last, // because last one is itself. for (uint32_t index = 1; index < parents_chain.size() - 1; ++index) { if (superclasses.find(parents_chain[index]) != superclasses.end()) { cls->rstate.force_unset_allowshrinking(); return; } } } }); }
bool Class::is_instanceof(Class* clss) { assert(!is_interface()); #ifdef VM_STATS UNSAFE_REGION_START VM_Statistics::get_vm_stats().num_type_checks++; if(this == clss) VM_Statistics::get_vm_stats().num_type_checks_equal_type++; if(clss->m_is_suitable_for_fast_instanceof) VM_Statistics::get_vm_stats().num_type_checks_fast_decision++; else if(clss->is_array()) VM_Statistics::get_vm_stats().num_type_checks_super_is_array++; else if(clss->is_interface()) VM_Statistics::get_vm_stats().num_type_checks_super_is_interface ++; else if((unsigned)clss->m_depth >= vm_max_fast_instanceof_depth()) VM_Statistics::get_vm_stats().num_type_checks_super_is_too_deep++; UNSAFE_REGION_END #endif // VM_STATS if(this == clss) return true; Global_Env* env = VM_Global_State::loader_env; if(is_array()) { Class* object_class = env->JavaLangObject_Class; assert(object_class != NULL); if(clss == object_class) return true; if(clss == env->java_io_Serializable_Class) return true; if(clss == env->java_lang_Cloneable_Class) return true; if(!clss->is_array()) return false; return class_is_subtype(get_array_element_class(), clss->get_array_element_class()); } else { if(clss->m_is_suitable_for_fast_instanceof) { return m_vtable->superclasses[clss->m_depth - 1] == clss; } if(!clss->is_interface()) { for(Class *c = this; c; c = c->get_super_class()) { if(c == clss) return true; } } else { for(Class *c = this; c; c = c->get_super_class()) { unsigned n_intf = c->get_number_of_superinterfaces(); for(unsigned i = 0; i < n_intf; i++) { Class* intf = c->get_superinterface(i); assert(intf); assert(intf->is_interface()); if(class_is_subtype(intf, clss)) return true; } } } } return false; }
struct usb_endpoint_descriptor *first_endpoint(const struct usb_interface_descriptor *d) { char *ptr = (char*)d; if (!is_interface(d)) { return 0; } ptr += d->bLength; return (struct usb_endpoint_descriptor*)ptr; }
bool is_assignable_to(const DexType* child, const DexType* parent) { // Check class hierarchy auto super = child; while (super != nullptr) { if (parent == super) return true; const auto cls = type_class(super); if (cls == nullptr) break; super = cls->get_super_class(); } // Check interface hierarchy DexClass* parent_cls = type_class(parent); return parent_cls && is_interface(parent_cls) && is_assignable_to_interface(child, parent); }
void AccessFlags::print_on(outputStream* st) const { if (is_public ()) st->print("public " ); if (is_private ()) st->print("private " ); if (is_protected ()) st->print("protected " ); if (is_static ()) st->print("static " ); if (is_final ()) st->print("final " ); if (is_synchronized()) st->print("synchronized "); if (is_volatile ()) st->print("volatile " ); if (is_transient ()) st->print("transient " ); if (is_native ()) st->print("native " ); if (is_interface ()) st->print("interface " ); if (is_abstract ()) st->print("abstract " ); if (is_strict ()) st->print("strict " ); if (is_synthetic ()) st->print("synthetic " ); if (is_old ()) st->print("{old} " ); if (is_obsolete ()) st->print("{obsolete} " ); }
void MethodBlock::invoke(DexMethod* meth, const std::vector<Location>& args) { always_assert(meth->is_concrete()); IROpcode opcode; if (meth->is_virtual()) { if (is_interface(type_class(meth->get_class()))) { opcode = OPCODE_INVOKE_INTERFACE; } else { opcode = OPCODE_INVOKE_VIRTUAL; } } else { if (is_static(meth)) { opcode = OPCODE_INVOKE_STATIC; } else { opcode = OPCODE_INVOKE_DIRECT; } } invoke(opcode, meth, args); }
/** * @return 1 or 0. */ STACKWORD instance_of (Object *obj, byte classIndex) { byte rtType; if (obj == null) return 0; rtType = get_class_index(obj); // TBD: support for interfaces if (is_interface (get_class_record(classIndex))) return 1; LABEL_INSTANCE: if (rtType == classIndex) return 1; if (rtType == JAVA_LANG_OBJECT) return 0; rtType = get_class_record(rtType)->parentClass; goto LABEL_INSTANCE; }
/* The interface can be followed not only by endpoint descriptors, but by other types of descriptors too. */ int get_interface_size(const struct usb_interface_descriptor *d) { struct usb_endpoint_descriptor *ed = 0; unsigned int i = 0; int len = 0; if (!is_interface(d)) { return 0; } len = d->bLength; ed = first_endpoint(d); for (i = 0; ed && i < d->bNumEndpoints; i += is_endpoint(ed), ed = next_endpoint(ed)) { len += ed->bLength; } return len; }
/** * Check to see if it is allowed to assign the an object of type srcCls * to an object of type dstCls. */ boolean is_assignable(const byte srcCls, const byte dstCls) { ClassRecord *dstRec; // Check common cases if (srcCls == dstCls || dstCls == JAVA_LANG_OBJECT) return true; dstRec = get_class_record(dstCls); if (is_interface(dstRec)) { // we are testing against an interface. So we use the associated interface // map to test if the src implements it... int base = get_interface_map_base(dstRec); // Special case all arrays implement cloneable if (dstCls == JAVA_LANG_CLONEABLE && is_array_class(get_class_record(srcCls))) return true; if (srcCls < base) return false; if (srcCls - base >= get_interface_map_len(dstRec)) return false; base = srcCls - base; return ((get_interface_map(dstRec)[base/8]) & (1 << (base%8))) != 0; } return sub_type_of(srcCls, dstCls); }
// ------------------------------------------------------------------ // ciFlags::print_klass_flags void ciFlags::print_klass_flags(outputStream* st) { if (is_public()) { st->print("public"); } else { st->print("DEFAULT_ACCESS"); } if (is_final()) { st->print(",final"); } if (is_super()) { st->print(",super"); } if (is_interface()) { st->print(",interface"); } if (is_abstract()) { st->print(",abstract"); } }
void TypeErasurePass::erase_model(const ModelSpec& spec, Scope& scope, PassManager& mgr, DexStoresVector& stores, ConfigFiles& cfg) { TRACE(TERA, 2, "[TERA] erasing %s model\n", spec.name.c_str()); Timer t("erase_model"); for (const auto root : spec.roots) { always_assert(!is_interface(type_class(root))); } auto model = Model::build_model(scope, stores, spec, cfg); model.update_redex_stats(mgr); auto mm = get_model_merger(); auto merger_classes = mm->merge_model(scope, stores, model, m_max_num_dispatch_target); mm->update_redex_stats(spec.class_name_prefix, mgr); delete mm; }
struct usb_interface_descriptor *find_interface( const struct usb_config_descriptor *d, int num, int altnum) { int cnt = get_total_interfaces(d); struct usb_interface_descriptor *iface = cnt > 0 ? first_interface(d, 0) : 0; int i = 0; for (i = 0; i < cnt && iface;) { if (!is_interface(iface)) { iface = next_descriptor(iface); } else if (iface->bInterfaceNumber == num && iface->bAlternateSetting == altnum) { return iface; } else { iface = next_interface(iface); ++i; } } return 0; }
/** * In some limited cases we can do type erasure on an interface when * implementors of the interface only implement that interface and have no * parent class other than java.lang.Object. We create a base class for those * implementors and use the new base class as root, and proceed with type * erasure as usual. */ void handle_interface_as_root(ModelSpec& spec, Scope& scope, DexStoresVector& stores) { TypeSet interface_roots; for (const auto root : spec.roots) { if (is_interface(type_class(root))) { interface_roots.insert(root); } } for (const auto interface_root : interface_roots) { auto empty_base = create_empty_base_type(spec, interface_root, scope, stores); if (empty_base != nullptr) { TRACE(TERA, 3, "Changing the root from %s to %s.\n", SHOW(interface_root), SHOW(empty_base)); spec.roots.insert(empty_base); add_class(type_class(empty_base), scope, stores); } // Remove interface roots regardless of whether an empty base was added. spec.roots.erase(interface_root); } }
bool Class::load_ancestors(Global_Env* env) { m_state = ST_LoadingAncestors; const String* superName = get_super_class_name(); if(superName == NULL) { if(env->InBootstrap() || get_name() != env->JavaLangClass_String) { // This class better be java.lang.Object if(get_name() != env->JavaLangObject_String) { // ClassFormatError std::stringstream ss; ss << get_name()->bytes << ": class does not have superclass " << "but the class is not java.lang.Object"; REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", ss.str().c_str()); return false; } } } else { // Load super class Class* superClass; m_super_class.name = NULL; superClass = m_class_loader->LoadVerifyAndPrepareClass(env, superName); if(superClass == NULL) { assert(exn_raised()); return false; } if(superClass->is_interface()) { REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/IncompatibleClassChangeError", "class " << m_name->bytes << " has interface " << superClass->get_name()->bytes << " as super class"); return false; } if(superClass->is_final()) { REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/VerifyError", m_name->bytes << " cannot inherit from final class " << superClass->get_name()->bytes); return false; } // super class was successfully loaded m_super_class.clss = superClass; if(m_super_class.cp_index) { m_const_pool.resolve_entry(m_super_class.cp_index, superClass); } // if it's an interface, its superclass must be java/lang/Object if(is_interface()) { if((env->JavaLangObject_Class != NULL) && (superClass != env->JavaLangObject_Class)) { std::stringstream ss; ss << get_name()->bytes << ": interface superclass is not java.lang.Object"; REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/ClassFormatError", ss.str().c_str()); return false; } } // Update the cha_first_child and cha_next_sibling fields. m_cha_first_child = NULL; if(has_super_class()) { m_cha_next_sibling = get_super_class()->m_cha_first_child; get_super_class()->m_cha_first_child = this; } } // // load in super interfaces // for(unsigned i = 0; i < m_num_superinterfaces; i++ ) { const String* intfc_name = m_superinterfaces[i].name; Class* intfc = m_class_loader->LoadVerifyAndPrepareClass(env, intfc_name); if(intfc == NULL) { assert(exn_raised()); return false; } if(!intfc->is_interface()) { REPORT_FAILED_CLASS_CLASS(m_class_loader, this, "java/lang/IncompatibleClassChangeError", get_name()->bytes << ": " << intfc->get_name()->bytes << " is not an interface"); return false; } // superinterface was successfully loaded m_superinterfaces[i].clss = intfc; if(m_superinterfaces[i].cp_index != 0) { // there are no constant pool entries for array classes m_const_pool.resolve_entry(m_superinterfaces[i].cp_index, intfc); } } // class, superclass, and superinterfaces successfully loaded m_state = ST_Loaded; if(!is_array()) m_package = m_class_loader->ProvidePackage(env, m_name, NULL); return true; }
bool Type::is_ref() const { return is_interface() || is_object() || is_alt() || is_generic() || is_nil(); }
int32_t main(int32_t argc, char *argv[]) { int res =0; uint8_t *eventbuf = NULL; uint8_t *dbgbuf = NULL; int32_t c; struct dbglog_slot *slot; int cnss_intf_len = strlen(CNSS_INTF) + 1; pthread_t thd_id; progname = argv[0]; uint16_t diag_type = 0; int32_t option_index = 0; static struct option long_options[] = { {"logfile", 1, NULL, 'f'}, {"reclimit", 1, NULL, 'r'}, {"console", 0, NULL, 'c'}, {"qxdm", 0, NULL, 'q'}, {"silent", 0, NULL, 's'}, {"debug", 0, NULL, 'd'}, { 0, 0, 0, 0} }; while (1) { c = getopt_long (argc, argv, "f:scqdr:", long_options, &option_index); if (c == -1) break; switch (c) { case 'f': memset(dbglogoutfile, 0, PATH_MAX); memcpy(dbglogoutfile, optarg, strlen(optarg)); optionflag |= LOGFILE_FLAG; break; case 'c': optionflag |= CONSOLE_FLAG; break; case 'q': optionflag |= QXDM_FLAG; break; case 'r': rec_limit = strtoul(optarg, NULL, 0); break; case 's': optionflag |= SILENT_FLAG; break; case 'd': optionflag |= DEBUG_FLAG; break; default: usage(); } } if (!(optionflag & (LOGFILE_FLAG | CONSOLE_FLAG | QXDM_FLAG | SILENT_FLAG | DEBUG_FLAG))) { usage(); return -1; } if (optionflag & QXDM_FLAG) { /* Intialize the fd required for diag APIs */ if (TRUE != Diag_LSM_Init(NULL)) { perror("Failed on Diag_LSM_Init\n"); return -1; } /* Register CALLABACK for QXDM input data */ DIAGPKT_DISPATCH_TABLE_REGISTER(DIAG_SUBSYS_WLAN, cnss_wlan_tbl); #ifdef ANDROID if(cnssdiagservice_cap_handle()) { printf("Cap bouncing failed EXIT!!!"); exit(1); } #endif } pthread_create(&thd_id, NULL, &cnss_intf_wait_receive, NULL); sock_fd = create_nl_socket(); if (sock_fd < 0) { fprintf(stderr, "Socket creation failed sock_fd 0x%x \n", sock_fd); return -1; } if (is_interface(CNSS_INTF, cnss_intf_len)) { initialize(sock_fd); cnssdiag_register_kernel_logging(sock_fd, nlh); } signal(SIGINT, stop); signal(SIGTERM, stop); if (optionflag & LOGFILE_FLAG) { if (rec_limit < RECLEN) { fprintf(stderr, "Too small maximum length (has to be >= %d)\n", RECLEN); close(sock_fd); free(nlh); return -1; } max_records = rec_limit; printf("Storing last %d records\n", max_records); log_out = fopen(dbglogoutfile, "w"); if (log_out == NULL) { perror("Failed to create output file"); close(sock_fd); free(nlh); return -1; } fwlog_res_file = "./reorder"; } parser_init(); while ( 1 ) { if ((res = recvmsg(sock_fd, &msg, 0)) < 0) continue; if ((res >= (int)sizeof(struct dbglog_slot)) || (nlh->nlmsg_type == WLAN_NL_MSG_CNSS_HOST_EVENT_LOG)) { process_cnss_diag_msg((tAniNlHdr *)nlh); memset(nlh,0,NLMSG_SPACE(MAX_MSG_SIZE)); } else { /* Ignore other messages that might be broadcast */ continue; } } /* Release the handle to Diag*/ Diag_LSM_DeInit(); if (optionflag & LOGFILE_FLAG) cleanup(); close(sock_fd); free(nlh); return 0; }
int main(int argc, char *argv[]) { struct lxc_container *c; char *cmd, *dev_name, *dst_name; int ret = 1; if (geteuid() != 0) { ERROR("%s must be run as root", argv[0]); exit(1); } if (lxc_arguments_parse(&my_args, argc, argv)) goto err; if (!my_args.log_file) my_args.log_file = "none"; if (lxc_log_init(my_args.name, my_args.log_file, my_args.log_priority, my_args.progname, my_args.quiet, my_args.lxcpath[0])) goto err; lxc_log_options_no_override(); c = lxc_container_new(my_args.name, my_args.lxcpath[0]); if (!c) { ERROR("%s doesn't exist", my_args.name); goto err; } if (!c->is_running(c)) { ERROR("Container %s is not running.", c->name); goto err1; } if (my_args.argc < 2) { ERROR("Error: no command given (Please see --help output)"); goto err1; } cmd = my_args.argv[0]; dev_name = my_args.argv[1]; if (my_args.argc < 3) dst_name = dev_name; else dst_name = my_args.argv[2]; if (strcmp(cmd, "add") == 0) { if (is_interface(dev_name, 1)) { ret = c->attach_interface(c, dev_name, dst_name); } else { ret = c->add_device_node(c, dev_name, dst_name); } if (ret != true) { ERROR("Failed to add %s to %s.", dev_name, c->name); ret = 1; goto err1; } INFO("Add %s to %s.", dev_name, c->name); } else if (strcmp(cmd, "del") == 0) { if (is_interface(dev_name, c->init_pid(c))) { ret = c->detach_interface(c, dev_name, dst_name); } else { ret = c->remove_device_node(c, dev_name, dst_name); } if (ret != true) { ERROR("Failed to del %s from %s.", dev_name, c->name); ret = 1; goto err1; } INFO("Delete %s from %s.", dev_name, c->name); } else { ERROR("Error: Please use add or del (Please see --help output)"); goto err1; } exit(0); err1: lxc_container_put(c); err: exit(ret); }
void RemoveBuildersPass::run_pass(DexStoresVector& stores, ConfigFiles&, PassManager& mgr) { if (mgr.no_proguard_rules()) { TRACE(BUILDERS, 1, "RemoveBuildersPass did not run because no Proguard configuration " "was provided."); return; } // Initialize couters. b_counter = {0, 0, 0, 0}; auto obj_type = get_object_type(); auto scope = build_class_scope(stores); for (DexClass* cls : scope) { if (is_annotation(cls) || is_interface(cls) || cls->get_super_class() != obj_type) { continue; } if (has_builder_name(cls->get_type())) { m_builders.emplace(cls->get_type()); } } std::unordered_set<DexType*> escaped_builders; walk::methods(scope, [&](DexMethod* m) { auto builders = created_builders(m); for (DexType* builder : builders) { if (escapes_stack(builder, m)) { TRACE(BUILDERS, 3, "%s escapes in %s\n", SHOW(builder), m->get_deobfuscated_name().c_str()); escaped_builders.emplace(builder); } } }); std::unordered_set<DexType*> stack_only_builders; for (DexType* builder : m_builders) { if (escaped_builders.find(builder) == escaped_builders.end()) { stack_only_builders.emplace(builder); } } std::unordered_set<DexType*> builders_and_supers; for (DexType* builder : stack_only_builders) { DexType* cls = builder; while (cls != nullptr && cls != obj_type) { builders_and_supers.emplace(cls); cls = type_class(cls)->get_super_class(); } } std::unordered_set<DexType*> this_escapes; for (DexType* cls_ty : builders_and_supers) { DexClass* cls = type_class(cls_ty); if (cls->is_external() || this_arg_escapes(cls, m_enable_buildee_constr_change)) { this_escapes.emplace(cls_ty); } } // set of builders that neither escape the stack nor pass their 'this' arg // to another function std::unordered_set<DexType*> no_escapes; for (DexType* builder : stack_only_builders) { DexType* cls = builder; bool hierarchy_has_escape = false; while (cls != nullptr) { if (this_escapes.find(cls) != this_escapes.end()) { hierarchy_has_escape = true; break; } cls = type_class(cls)->get_super_class(); } if (!hierarchy_has_escape) { no_escapes.emplace(builder); } } size_t dmethod_count = 0; size_t vmethod_count = 0; size_t build_count = 0; for (DexType* builder : no_escapes) { auto cls = type_class(builder); auto buildee = get_buildee(builder); dmethod_count += cls->get_dmethods().size(); vmethod_count += cls->get_vmethods().size(); for (DexMethod* m : cls->get_vmethods()) { if (m->get_proto()->get_rtype() == buildee) { build_count++; } } } std::unordered_set<DexClass*> trivial_builders = get_trivial_builders(m_builders, no_escapes); std::unordered_set<DexClass*> kept_builders = get_builders_with_subclasses(scope); PassConfig pc(mgr.get_config()); BuilderTransform b_transform(pc, scope, stores, false); // Inline non init methods. std::unordered_set<DexClass*> removed_builders; walk::methods(scope, [&](DexMethod* method) { auto builders = created_builders(method); for (DexType* builder : builders) { if (method->get_class() == builder) { continue; } DexClass* builder_cls = type_class(builder); // Filter out builders that we cannot remove. if (kept_builders.find(builder_cls) != kept_builders.end()) { continue; } // Check it is a trivial one. if (trivial_builders.find(builder_cls) != trivial_builders.end()) { DexMethod* method_copy = DexMethod::make_method_from( method, method->get_class(), DexString::make_string(method->get_name()->str() + "$redex_builders")); bool was_not_removed = !b_transform.inline_methods( method, builder, &get_non_init_methods) || !remove_builder_from(method, builder_cls, b_transform); if (was_not_removed) { kept_builders.emplace(builder_cls); method->set_code(method_copy->release_code()); } else { b_counter.methods_cleared++; removed_builders.emplace(builder_cls); } DexMethod::erase_method(method_copy); } } }); // No need to remove the builders here, since `RemoveUnreachable` will // take care of it. gather_removal_builder_stats(removed_builders, kept_builders); mgr.set_metric("total_builders", m_builders.size()); mgr.set_metric("stack_only_builders", stack_only_builders.size()); mgr.set_metric("no_escapes", no_escapes.size()); mgr.incr_metric(METRIC_CLASSES_REMOVED, b_counter.classes_removed); mgr.incr_metric(METRIC_METHODS_REMOVED, b_counter.methods_removed); mgr.incr_metric(METRIC_FIELDS_REMOVED, b_counter.fields_removed); mgr.incr_metric(METRIC_METHODS_CLEARED, b_counter.methods_cleared); TRACE(BUILDERS, 1, "Total builders: %d\n", m_builders.size()); TRACE(BUILDERS, 1, "Stack-only builders: %d\n", stack_only_builders.size()); TRACE(BUILDERS, 1, "Stack-only builders that don't let `this` escape: %d\n", no_escapes.size()); TRACE(BUILDERS, 1, "Stats for unescaping builders:\n"); TRACE(BUILDERS, 1, "\tdmethods: %d\n", dmethod_count); TRACE(BUILDERS, 1, "\tvmethods: %d\n", vmethod_count); TRACE(BUILDERS, 1, "\tbuild methods: %d\n", build_count); TRACE(BUILDERS, 1, "Trivial builders: %d\n", trivial_builders.size()); TRACE(BUILDERS, 1, "Classes removed: %d\n", b_counter.classes_removed); TRACE(BUILDERS, 1, "Methods removed: %d\n", b_counter.methods_removed); TRACE(BUILDERS, 1, "Fields removed: %d\n", b_counter.fields_removed); TRACE(BUILDERS, 1, "Methods cleared: %d\n", b_counter.methods_cleared); }