Esempio n. 1
0
/**
 * Check collisions in method definition.
 */
EscapeReason OptimizationImpl::check_method_collision(DexType* intf,
                                                      SingleImplData& data) {
  for (auto method : data.methoddefs) {
    auto meth_it = new_methods.find(method);
    if (meth_it != new_methods.end()) method = meth_it->second;
    auto proto = get_or_make_proto(intf, data.cls, method->get_proto());
    assert(proto != method->get_proto());
    DexMethod* collision = find_collision(method->get_name(),
                                          proto,
                                          type_class(method->get_class()),
                                          method->is_virtual());
    if (collision) return SIG_COLLISION;
  }
  return NO_ESCAPE;
}
Esempio n. 2
0
/**
 * Rewrite all methods sigs by creating new ones. Remove old methods and push
 * the new to the proper class method list.
 */
void OptimizationImpl::set_method_defs(DexType* intf,
                                       SingleImplData& data) {
  for (auto method : data.methoddefs) {
    TRACE(INTF, 3, "(MDEF) %s\n", SHOW(method));
    auto meth = method;
    auto meth_it = new_methods.find(meth);
    if (meth_it != new_methods.end()) {
      // if a method rewrite existed it must not be on a single impl
      // given we have escaped to next pass all collisions
      always_assert(meth_it->second->is_def());
      meth = static_cast<DexMethod*>(meth_it->second);
      TRACE(INTF, 4, "(MDEF) current: %s\n", SHOW(meth));
      assert(!single_impls->is_single_impl(method->get_class()) ||
             single_impls->is_escaped(method->get_class()));
      assert(!single_impls->is_single_impl(meth->get_class()) ||
             single_impls->is_escaped(meth->get_class()));
    }
    auto proto = get_or_make_proto(intf, data.cls, meth->get_proto());
    TRACE(INTF,
          5,
          "(MDEF) make_method: %s.%s - %s => %s\n",
          SHOW(meth->get_class()),
          SHOW(meth->get_name()),
          SHOW(meth->get_proto()),
          SHOW(proto));
    assert(proto != meth->get_proto());
    auto new_meth = static_cast<DexMethod*>(DexMethod::make_method(
        meth->get_class(), meth->get_name(), proto));
    // new_meth may have already existed in RedexContext, so
    // we need to make sure it isn't concrete.
    // TODO: this is horrible. After we remove methods, we shouldn't
    // have these zombies lying around.
    new_meth->clear_annotations();
    new_meth->make_non_concrete();
    new_meth->set_deobfuscated_name(meth->get_deobfuscated_name());
    new_meth->rstate = meth->rstate;
    assert(new_meth != meth);
    setup_method(meth, new_meth);
    new_methods[method] = new_meth;
    auto owner = type_class(new_meth->get_class());
    owner->remove_method(meth);
    owner->add_method(new_meth);
    TRACE(INTF, 3, "(MDEF)\t=> %s\n", SHOW(new_meth));
  }
}
Esempio n. 3
0
/**
 * Rewrite all method refs.
 */
void OptimizationImpl::set_method_refs(DexType* intf,
                                       SingleImplData& data) {
  for (auto mrefit : data.methodrefs) {
    auto method = mrefit.first;
    TRACE(INTF, 3, "(MREF)  %s\n", SHOW(method));
    auto new_meth = method;
    auto meth_it = new_methods.find(new_meth);
    if (meth_it != new_methods.end()) {
      // if a method rewrite existed it must not be on a single impl
      // given we have escaped to "next pass" all collisions
      new_meth = meth_it->second;
      TRACE(INTF, 4, "current: %s\n", SHOW(new_meth));
      assert(!single_impls->is_single_impl(method->get_class()) ||
             single_impls->is_escaped(method->get_class()));
      assert(!single_impls->is_single_impl(new_meth->get_class()) ||
             single_impls->is_escaped(new_meth->get_class()));
    }
    // next 2 lines will generate no new proto or method when the ref matches
    // a def, which should be very common.
    // However it does not seem too much of an overkill and more
    // straightforward that any logic that manages that.
    // Both creation of protos or methods is "interned" and so the same
    // method would be returned if there is nothing to change and create.
    // Still we need to change the opcodes where we assert the new method
    // to go in the opcode is in fact different than what was there.
    auto proto = get_or_make_proto(intf, data.cls, new_meth->get_proto());
    auto created_meth = DexMethod::make_method(
            new_meth->get_class(), new_meth->get_name(), proto);
    if (created_meth->is_def() && method->is_def()) {
      static_cast<DexMethod*>(created_meth)->set_deobfuscated_name(
          static_cast<DexMethod*>(method)->get_deobfuscated_name());
      static_cast<DexMethod*>(created_meth)->rstate =
          static_cast<DexMethod*>(method)->rstate;
    }
    new_methods[method] = created_meth;
    TRACE(INTF, 3, "(MREF)\t=> %s\n", SHOW(created_meth));
    for (auto opcode : mrefit.second) {
      TRACE(INTF, 3, "(MREF) %s\n", SHOW(opcode));
      assert(opcode->get_method() != created_meth);
      opcode->set_method(created_meth);
      TRACE(INTF, 3, "(MREF) \t=> %s\n", SHOW(opcode));
    }
  }
}
Esempio n. 4
0
/**
 * Rewrite all methods sigs by creating new ones. Remove old methods and push
 * the new to the proper class method list.
 */
void OptimizationImpl::rewrite_method_defs(DexType* intf,
                                           SingleImplData& data) {
  for (auto method : data.methoddefs) {
    TRACE(INTF, 3, "(MDEF) %s\n", SHOW(method));
    auto meth = method;
    auto meth_it = new_methods.find(meth);
    if (meth_it != new_methods.end()) {
      // if a method rewrite existed it must not be on a single impl
      // given we have escaped to next pass all collisions
      meth = meth_it->second;
      TRACE(INTF, 4, "(MDEF) current: %s\n", SHOW(meth));
      assert(!single_impls->is_single_impl(method->get_class()) ||
             single_impls->is_escaped(method->get_class()));
      assert(!single_impls->is_single_impl(meth->get_class()) ||
             single_impls->is_escaped(meth->get_class()));
    }
    auto proto = get_or_make_proto(intf, data.cls, meth->get_proto());
    TRACE(INTF,
          5,
          "(MDEF) make_method: %s.%s - %s => %s\n",
          SHOW(meth->get_class()),
          SHOW(meth->get_name()),
          SHOW(meth->get_proto()),
          SHOW(proto));
    assert(proto != meth->get_proto());
    auto new_meth = DexMethod::make_method(
        meth->get_class(), meth->get_name(), proto);
    assert(new_meth != meth);
    setup_method(meth, new_meth);
    new_methods[method] = new_meth;
    auto owner = type_class(new_meth->get_class());
    owner->remove_method(meth);
    owner->add_method(new_meth);
    TRACE(INTF, 3, "(MDEF)\t=> %s\n", SHOW(new_meth));
  }
}