Esempio n. 1
0
int main(int argc, char* argv[]) {
  if (argc < 2) {
    std::cerr << "Usage: ./TestGenerator classes.dex" << std::endl;
  }
  auto dex = argv[1];

  g_redex = new RedexContext();
  auto classes = load_classes_from_dex(dex);
  auto runner_cls =
      std::find_if(classes.begin(), classes.end(), [](const DexClass* cls) {
        return cls->get_name() ==
               DexString::get_string(
                   "Lcom/facebook/redex/equivalence/EquivalenceMain;");
      });

  redex_assert(runner_cls != classes.end());

  EquivalenceTest::generate_all(*runner_cls);

  Json::Value json(Json::objectValue);
  ConfigFiles conf(json);
  std::unique_ptr<PositionMapper> pos_mapper(PositionMapper::make("", ""));

  DexStore store("classes");
  store.set_dex_magic(load_dex_magic_from_dex(dex));
  store.add_classes(classes);
  DexStoresVector stores;
  stores.emplace_back(std::move(store));
  instruction_lowering::run(stores);

  write_classes_to_dex(dex,
                       &classes,
                       nullptr /* LocatorIndex* */,
                       false /* name-based locators */,
                       0,
                       0,
                       conf,
                       pos_mapper.get(),
                       nullptr,
                       nullptr,
                       nullptr /* IODIMetadata* */,
                       stores[0].get_dex_magic());

  delete g_redex;
  return 0;
}
Esempio n. 2
0
int main(int argc, char* argv[]) {
  signal(SIGSEGV, crash_backtrace);
  signal(SIGABRT, crash_backtrace);
  signal(SIGBUS, crash_backtrace);

  g_redex = new RedexContext();

  auto passes = create_passes();

  Arguments args;
  std::vector<KeepRule> rules;
  // Currently there are two sources that specify the library jars:
  // 1. The jar_path argument, which may specify one library jar.
  // 2. The library_jars vector, which lists the library jars specified in
  //    the ProGuard configuration.
  // If -jarpath specified a library jar it is appended to the
  // library_jars vector so this vector can be used to iterate over
  // all the library jars regardless of whether they were specified
  // on the command line or ProGuard file.
  // TODO: Make the command line -jarpath option like a colon separated
  //       list of library JARS.
  std::set<std::string> library_jars;
  auto start = parse_args(argc, argv, args);
  if (!dir_is_writable(args.out_dir)) {
    fprintf(stderr,
            "outdir %s is not a writable directory\n",
            args.out_dir.c_str());
    exit(1);
  }

  if (!args.proguard_config.empty()) {
    if (!load_proguard_config_file(
            args.proguard_config.c_str(), &rules, &library_jars)) {
      fprintf(stderr,
              "ERROR: Unable to open proguard config %s\n",
              args.proguard_config.c_str());
      // For now tolerate missing or unparseable ProGuard configuration files.
      // start = 0;
    }
  } else {
    TRACE(MAIN,
          1,
          "Skipping parsing the proguard config file "
          "because no file was specified\n");
  }

  for (const auto jar_path : args.jar_paths) {
    std::stringstream jar_stream(jar_path);
    std::string dependent_jar_path;
    while (std::getline(jar_stream, dependent_jar_path, ':')) {
      TRACE(MAIN,
            2,
            "Dependent JAR specified on command-line: %s\n",
            dependent_jar_path.c_str());
      library_jars.emplace(dependent_jar_path);
    }
  }

  if (start == 0 || start == argc) {
    usage();
    exit(1);
  }

  DexClassesVector dexen;
  for (int i = start; i < argc; i++) {
    dexen.emplace_back(load_classes_from_dex(argv[i]));
  }

  for (const auto& library_jar : library_jars) {
    TRACE(MAIN, 1, "LIBRARY JAR: %s\n", library_jar.c_str());
    if (!load_jar_file(library_jar.c_str())) {
      fprintf(
          stderr,
          "WARNING: Error in jar %s - continue. This may lead to unexpected "
          "behavior, please check your jars\n",
          library_jar.c_str());
    }
  }

  ConfigFiles cfg(args.config);
  cfg.using_seeds = false;
  if (!args.seeds_filename.empty()) {
    cfg.using_seeds = init_seed_classes(args.seeds_filename) > 0;
  }

  PassManager manager(passes, rules, args.config);
  manager.run_passes(dexen, cfg);

  TRACE(MAIN, 1, "Writing out new DexClasses...\n");

  LocatorIndex* locator_index = nullptr;
  if (args.config.get("emit_locator_strings", false).asBool()) {
    TRACE(LOC,
          1,
          "Will emit class-locator strings for classloader optimization\n");
    locator_index = new LocatorIndex(make_locator_index(dexen));
  }

  dex_output_stats_t totals;
  std::vector<dex_output_stats_t> dexes_stats;

  auto pos_output = args.config.get("line_number_map", "").asString();
  std::unique_ptr<PositionMapper> pos_mapper(PositionMapper::make(pos_output));

  for (size_t i = 0; i < dexen.size(); i++) {
    std::stringstream ss;
    ss << args.out_dir + "/classes";
    if (i > 0) {
      ss << (i + 1);
    }
    ss << ".dex";
    auto stats = write_classes_to_dex(
      ss.str(),
      &dexen[i],
      locator_index,
      i,
      cfg,
      args.config,
      pos_mapper.get());
    totals += stats;
    dexes_stats.push_back(stats);
  }

  auto stats_output = args.config.get("stats_output", "").asString();
  auto method_move_map = args.config.get("method_move_map", "").asString();

  pos_mapper->write_map();
  output_stats(stats_output.c_str(), totals, dexes_stats, manager);
  output_moved_methods_map(method_move_map.c_str(), dexen, cfg);
  print_warning_summary();
  delete g_redex;
  TRACE(MAIN, 1, "Done.\n");

  return 0;
}