Esempio n. 1
0
std::unique_ptr<intraprocedural::FixpointIterator> analyze_procedure(
    const DexMethod* method,
    const WholeProgramState& wps,
    ArgumentDomain args) {
  always_assert(method->get_code() != nullptr);
  auto& code = *method->get_code();
  // Currently, our callgraph does not include calls to non-devirtualizable
  // virtual methods. So those methods may appear unreachable despite being
  // reachable.
  if (args.is_bottom()) {
    args.set_to_top();
  } else if (!args.is_top()) {
    TRACE(ICONSTP, 3, "Have args for %s: %s\n", SHOW(method), SHOW(args));
  }

  auto env = env_with_params(&code, args);
  DexType* class_under_init{nullptr};
  if (is_clinit(method)) {
    class_under_init = method->get_class();
    set_encoded_values(type_class(class_under_init), &env);
  }
  TRACE(ICONSTP, 5, "%s\n", SHOW(code.cfg()));

  auto intra_cp = std::make_unique<intraprocedural::FixpointIterator>(
      code.cfg(),
      CombinedAnalyzer(class_under_init,
                       &wps,
                       EnumFieldAnalyzerState(),
                       BoxedBooleanAnalyzerState(),
                       nullptr));
  intra_cp->run(env);

  return intra_cp;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;
}
Esempio n. 4
0
/*
 * There's no "good way" to differentiate blank vs. non-blank
 * finals.  So, we just scan the code in the CL-init.  If
 * it's sput there, then it's a blank.  Lame, agreed, but functional.
 *
 */
void get_sput_in_clinit(DexClass* clazz,
                        std::unordered_map<DexField*, bool>& blank_statics) {
  auto methods = clazz->get_dmethods();
  for (auto method : methods) {
    if (is_clinit(method)) {
      always_assert_log(is_static(method) && is_constructor(method),
          "static constructor doesn't have the proper access bits set\n");
      auto& code = method->get_code();
      auto opcodes = code->get_instructions();
      for (auto opcode : opcodes) {
        if (opcode->has_fields() && is_sput(opcode->opcode())) {
          auto fieldop = static_cast<DexOpcodeField*>(opcode);
          auto field = resolve_field(fieldop->field(), FieldSearch::Static);
          if (field == nullptr || !field->is_concrete()) continue;
          if (field->get_class() != clazz->get_type()) continue;
          blank_statics[field] = true;
        }
      }
    }
  }
}