Пример #1
0
/*
 * Check that analyze_enum_clinit returns the correct enum field -> ordinal
 * mapping.
 */
TEST_F(RedexTest, OrdinalAnalysis) {
  always_assert(load_class_file(std::getenv("enum_class_file")));

  auto dexfile = std::getenv("dexfile");
  std::vector<DexStore> stores;
  DexMetadata dm;
  dm.set_id("classes");
  DexStore root_store(dm);
  root_store.add_classes(load_classes_from_dex(dexfile));
  auto scope = build_class_scope(root_store.get_dexen());

  auto enumA = type_class(DexType::get_type(ENUM_A));
  auto enum_field_to_ordinal = optimize_enums::analyze_enum_clinit(enumA);
  auto enumA_zero = static_cast<DexField*>(
      DexField::get_field("Lcom/facebook/redextest/EnumA;.TYPE_A_0:Lcom/"
                          "facebook/redextest/EnumA;"));
  auto enumA_one = static_cast<DexField*>(
      DexField::get_field("Lcom/facebook/redextest/EnumA;.TYPE_A_1:Lcom/"
                          "facebook/redextest/EnumA;"));
  auto enumA_two = static_cast<DexField*>(
      DexField::get_field("Lcom/facebook/redextest/EnumA;.TYPE_A_2:Lcom/"
                          "facebook/redextest/EnumA;"));
  EXPECT_EQ(enum_field_to_ordinal.at(enumA_zero), 0);
  EXPECT_EQ(enum_field_to_ordinal.at(enumA_one), 1);
  EXPECT_EQ(enum_field_to_ordinal.at(enumA_two), 2);
}
Пример #2
0
TEST(DedupBlocksTest, useSwitch) {
  g_redex = new RedexContext();

  const char* dexfile = std::getenv("dexfile");
  EXPECT_NE(nullptr, dexfile);

  std::vector<DexStore> stores;
  DexMetadata dm;
  dm.set_id("classes");
  DexStore root_store(dm);
  root_store.add_classes(load_classes_from_dex(dexfile));
  DexClasses& classes = root_store.get_dexen().back();
  stores.emplace_back(std::move(root_store));

  TRACE(RME, 1, "Code before:\n");
  for (const auto& cls : classes) {
    TRACE(RME, 1, "Class %s\n", SHOW(cls));
    for (const auto& m : cls->get_vmethods()) {
      TRACE(RME, 1, "\nmethod %s:\n", SHOW(m));
      IRCode* code = m->get_code();
      code->build_cfg(true);
      EXPECT_EQ(2, count_sgets(code->cfg()));
      code->clear_cfg();
    }
  }

  auto copy_prop = new CopyPropagationPass();
  copy_prop->m_config.static_finals = true;
  copy_prop->m_config.wide_registers = true;
  std::vector<Pass*> passes = {
    copy_prop
  };

  PassManager manager(passes);
  manager.set_testing_mode();

  Json::Value conf_obj = Json::nullValue;
  Scope external_classes;
  ConfigFiles dummy_cfg(conf_obj);
  manager.run_passes(stores, external_classes, dummy_cfg);

  TRACE(RME, 1, "Code after:\n");
  for (const auto& cls : classes) {
    for (const auto& m : cls->get_vmethods()) {
      TRACE(RME, 1, "\nmethod %s:\n", SHOW(m));
      IRCode* code = m->get_code();
      code->build_cfg(true);
      if (strcmp(m->get_name()->c_str(), "remove") == 0) {
        EXPECT_EQ(1, count_sgets(code->cfg()));
      } else {
        EXPECT_EQ(2, count_sgets(code->cfg()));
      }
      code->clear_cfg();
    }
  }
}
Пример #3
0
void run_passes(std::vector<Pass*> passes, std::vector<DexClass*> classes) {
  std::vector<DexStore> stores;
  DexMetadata dm;
  dm.set_id("classes");
  DexStore store(dm);
  store.add_classes(classes);
  stores.emplace_back(std::move(store));
  PassManager manager(passes);
  manager.set_testing_mode();

  Scope external_classes;
  Json::Value conf_obj = Json::nullValue;
  ConfigFiles dummy_config(conf_obj);
  manager.run_passes(stores, external_classes, dummy_config);
}
Пример #4
0
TEST(PropagationTest1, localDCE1) {
  g_redex = new RedexContext();

  const char* dexfile = std::getenv("dexfile");
  ASSERT_NE(nullptr, dexfile);

  std::vector<DexStore> stores;
  DexMetadata dm;
  dm.set_id("classes");
  DexStore root_store(dm);
  root_store.add_classes(load_classes_from_dex(dexfile));
  DexClasses& classes = root_store.get_dexen().back();
  stores.emplace_back(std::move(root_store));
  std::cout << "Loaded classes: " << classes.size() << std::endl ;

  TRACE(DCE, 2, "Code before:\n");
  for(const auto& cls : classes) {
    TRACE(DCE, 2, "Class %s\n", SHOW(cls));
    for (const auto& dm : cls->get_dmethods()) {
      TRACE(DCE, 2, "dmethod: %s\n",  dm->get_name()->c_str());
      if (strcmp(dm->get_name()->c_str(), "propagate") == 0) {
        TRACE(DCE, 2, "dmethod: %s\n",  SHOW(dm->get_code()));
      }
    }
  }

  std::vector<Pass*> passes = {
    new PeepholePass(),
    new LocalDcePass(),
  };

  PassManager manager(passes);
  manager.set_testing_mode();

  Json::Value conf_obj = Json::nullValue;
  ConfigFiles dummy_cfg(conf_obj);
  manager.run_passes(stores, dummy_cfg);

  TRACE(DCE, 2, "Code after:\n");
  for(const auto& cls : classes) {
    TRACE(DCE, 2, "Class %s\n", SHOW(cls));
    for (const auto& dm : cls->get_dmethods()) {
      TRACE(DCE, 2, "dmethod: %s\n",  dm->get_name()->c_str());
      if (strcmp(dm->get_name()->c_str(), "propagate") == 0) {
        TRACE(DCE, 2, "dmethod: %s\n",  SHOW(dm->get_code()));
        for (auto& mie : InstructionIterable(dm->get_code())) {
          auto instruction = mie.insn;
          // Make sure there is no invoke-virtual in the optimized method.
          ASSERT_NE(instruction->opcode(), OPCODE_INVOKE_VIRTUAL);
          // Make sure there is no const-class in the optimized method.
          ASSERT_NE(instruction->opcode(), OPCODE_CONST_CLASS);
        }
      }
    }
  }

}
Пример #5
0
  virtual void SetUp() override {
    saved_context = g_redex;
    g_redex = new RedexContext();

    const char* dexfile = std::getenv("dexfile");
    ASSERT_NE(nullptr, dexfile);

    DexMetadata dm;
    dm.set_id("classes");
    DexStore root_store(dm);
    root_store.add_classes(load_classes_from_dex(dexfile));
    DexClasses& classes = root_store.get_dexen().back();
    stores.emplace_back(std::move(root_store));
    ASSERT_EQ(classes.size(), 1) << "Expected exactly one class in " << dexfile;
    dex_class = classes.at(0);
    ASSERT_NE(nullptr, dex_class);
  }
Пример #6
0
TEST(ResultPropagationTest, useSwitch) {
  g_redex = new RedexContext();

  const char* dexfile = std::getenv("dexfile");
  EXPECT_NE(nullptr, dexfile);

  std::vector<DexStore> stores;
  DexMetadata dm;
  dm.set_id("classes");
  DexStore root_store(dm);
  root_store.add_classes(load_classes_from_dex(dexfile));
  DexClasses& classes = root_store.get_dexen().back();
  stores.emplace_back(std::move(root_store));

  std::vector<Pass*> passes = {
      new ResultPropagationPass(),
  };

  PassManager manager(passes);
  manager.set_testing_mode();

  Json::Value conf_obj = Json::nullValue;
  ConfigFiles dummy_cfg(conf_obj);
  manager.run_passes(stores, dummy_cfg);

  int num_test_classes = 0;
  const char* test_class_prefix = "Lcom/facebook/redextest/ResultPropagation$";
  const char* test_method_prefix = "returns_";
  for (const auto& cls : classes) {
    if (strncmp(cls->get_name()->c_str(), test_class_prefix,
                strlen(test_class_prefix)) == 0) {
      TRACE(RP, 1, "test class %s\n", cls->get_name()->c_str());
      num_test_classes++;
      int num_tests_in_class = 0;
      for (const auto& m : cls->get_vmethods()) {
        const auto method_name = m->get_name()->c_str();
        TRACE(RP, 1, " test method %s\n", method_name);
        EXPECT_EQ(strncmp(method_name, test_method_prefix,
                          strlen(test_method_prefix)),
                  0);
        const auto suffix = method_name + strlen(test_method_prefix);
        boost::optional<ParamIndex> expected;
        if (strcmp(suffix, "none") != 0) {
          expected = atoi(suffix);
        }

        IRCode* code = m->get_code();
        code->build_cfg(/* editable */ true);
        auto actual = find_return_param_index(code->cfg());
        code->clear_cfg();
        if (expected) {
          EXPECT_TRUE(actual);
          EXPECT_EQ(*actual, *expected);
        } else {
          EXPECT_FALSE(actual);
        }
        num_tests_in_class++;
      }
      EXPECT_EQ(num_tests_in_class, 1);
    }
  }
  EXPECT_EQ(num_test_classes, 6);
}