void DexOpcodeString::encode(DexOutputIdx* dodx, uint16_t*& insns) { encode_opcode(dodx, insns); uint32_t sidx = dodx->stringidx(m_string); uint16_t idx = (uint16_t)sidx; if (!jumbo()) { always_assert_log(sidx == idx, "Attempt to encode jumbo string in non-jumbo opcode: %s", m_string->c_str()); *insns++ = idx; return; } if (sidx == idx) { opt_warn(NON_JUMBO_STRING, "%s\n", m_string->c_str()); } *insns++ = idx; idx = sidx >> 16; *insns++ = idx; }
void AddRedexTxtToApkPass::run_pass(DexStoresVector& /* unused */, ConfigFiles& conf, PassManager& /* unused */) { std::string apk_dir; conf.get_json_config().get("apk_dir", "", apk_dir); if (!apk_dir.size()) { TRACE(ADD_REDEX_TXT, 2, "apk_dir not set, so not writing redex.txt\n"); return; } std::string out_file_name = apk_dir + "/redex.txt"; std::ofstream redex_txt(out_file_name); if (redex_txt.is_open()) { redex_txt << "Optimized by Redex" << std::endl << "http://fbredex.com/" << std::endl; redex_txt.close(); } else { opt_warn(CANT_WRITE_FILE, "Unable to write file %s\n", out_file_name.c_str()); } }
static void strip_src_strings( DexStoresVector& stores, const char* map_path, PassManager& mgr) { size_t shortened = 0; size_t string_savings = 0; std::unordered_map<DexString*, std::vector<DexString*>> global_src_strings; std::unordered_set<DexString*> shortened_used; for (auto& classes : DexStoreClassesIterator(stores)) { for (auto const& clazz : classes) { auto src_string = clazz->get_source_file(); if (src_string) { // inserting actual source files into this set will cause them to not // get used --- as the whole point of this analysis is to substitute // source file strings shortened_used.insert(src_string); } } } for (auto& classes : DexStoreClassesIterator(stores)) { std::unordered_map<DexString*, DexString*> src_to_shortened; std::vector<DexString*> current_dex_strings; for (auto const& clazz : classes) { clazz->gather_strings(current_dex_strings); } sort_unique(current_dex_strings, compare_dexstrings); // reverse current_dex_strings vector, so that we prefer strings that will // get smaller indices std::reverse(std::begin(current_dex_strings), std::end(current_dex_strings)); for (auto const& clazz : classes) { auto src_string = clazz->get_source_file(); if (!src_string) { continue; } DexString* shortened_src_string = nullptr; if (src_to_shortened.count(src_string) == 0) { shortened_src_string = get_suitable_string(shortened_used, current_dex_strings); if (!shortened_src_string) { opt_warn(UNSHORTENED_SRC_STRING, "%s\n", SHOW(src_string)); shortened_src_string = src_string; } else { shortened++; string_savings += strlen(src_string->c_str()); } src_to_shortened[src_string] = shortened_src_string; shortened_used.emplace(shortened_src_string); global_src_strings[src_string].push_back(shortened_src_string); } else { shortened_src_string = src_to_shortened[src_string]; } clazz->set_source_file(shortened_src_string); } } TRACE(SHORTEN, 1, "src strings shortened %ld, %lu bytes saved\n", shortened, string_savings); mgr.incr_metric(METRIC_SHORTENED_STRINGS, shortened); mgr.incr_metric(METRIC_BYTES_SAVED, string_savings); // generate mapping FILE* fd = fopen(map_path, "w"); if (fd == nullptr) { perror("Error writing mapping file"); return; } for (auto it : global_src_strings) { auto desc_vector = it.second; sort_unique(desc_vector); fprintf(fd, "%s ->", it.first->c_str()); for (auto str : desc_vector) { fprintf(fd, " %s,", str->c_str()); } fprintf(fd, "\n"); } fclose(fd); }