| /* |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include <android-base/file.h> |
| |
| #include "dex/dex_file.h" |
| #include "dex/dex_file_loader.h" |
| |
| #include <sstream> |
| |
| namespace art { |
| |
| struct VeridexOptions { |
| const char* dex_file = nullptr; |
| const char* core_stubs = nullptr; |
| const char* blacklist = nullptr; |
| const char* light_greylist = nullptr; |
| const char* dark_greylist = nullptr; |
| }; |
| |
| static const char* Substr(const char* str, int index) { |
| return str + index; |
| } |
| |
| static bool StartsWith(const char* str, const char* val) { |
| return strlen(str) >= strlen(val) && memcmp(str, val, strlen(val)) == 0; |
| } |
| |
| static void ParseArgs(VeridexOptions* options, int argc, char** argv) { |
| // Skip over the command name. |
| argv++; |
| argc--; |
| |
| static const char* kDexFileOption = "--dex-file="; |
| static const char* kStubsOption = "--core-stubs="; |
| static const char* kBlacklistOption = "--blacklist="; |
| static const char* kDarkGreylistOption = "--dark-greylist="; |
| static const char* kLightGreylistOption = "--light-greylist="; |
| |
| for (int i = 0; i < argc; ++i) { |
| if (StartsWith(argv[i], kDexFileOption)) { |
| options->dex_file = Substr(argv[i], strlen(kDexFileOption)); |
| } else if (StartsWith(argv[i], kStubsOption)) { |
| options->core_stubs = Substr(argv[i], strlen(kStubsOption)); |
| } else if (StartsWith(argv[i], kBlacklistOption)) { |
| options->blacklist = Substr(argv[i], strlen(kBlacklistOption)); |
| } else if (StartsWith(argv[i], kDarkGreylistOption)) { |
| options->dark_greylist = Substr(argv[i], strlen(kDarkGreylistOption)); |
| } else if (StartsWith(argv[i], kLightGreylistOption)) { |
| options->light_greylist = Substr(argv[i], strlen(kLightGreylistOption)); |
| } |
| } |
| } |
| |
| static std::vector<std::string> Split(const std::string& str, char sep) { |
| std::vector<std::string> tokens; |
| std::string tmp; |
| std::istringstream iss(str); |
| while (std::getline(iss, tmp, sep)) { |
| tokens.push_back(tmp); |
| } |
| return tokens; |
| } |
| |
| class Veridex { |
| public: |
| static int Run(int argc, char** argv) { |
| VeridexOptions options; |
| ParseArgs(&options, argc, argv); |
| |
| std::vector<std::string> boot_content; |
| std::vector<std::string> app_content; |
| std::vector<std::unique_ptr<const DexFile>> boot_dex_files; |
| std::vector<std::unique_ptr<const DexFile>> app_dex_files; |
| std::string error_msg; |
| |
| // Read the boot classpath. |
| std::vector<std::string> boot_classpath = Split(options.core_stubs, ':'); |
| boot_content.resize(boot_classpath.size()); |
| uint32_t i = 0; |
| for (const std::string& str : boot_classpath) { |
| if (!Load(str, boot_content[i++], &boot_dex_files, &error_msg)) { |
| LOG(ERROR) << error_msg; |
| return 1; |
| } |
| } |
| |
| // Read the apps dex files. |
| std::vector<std::string> app_files = Split(options.dex_file, ':'); |
| app_content.resize(app_files.size()); |
| i = 0; |
| for (const std::string& str : app_files) { |
| if (!Load(str, app_content[i++], &app_dex_files, &error_msg)) { |
| LOG(ERROR) << error_msg; |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| private: |
| static bool Load(const std::string& filename, |
| std::string& content, |
| std::vector<std::unique_ptr<const DexFile>>* dex_files, |
| std::string* error_msg) { |
| if (filename.empty()) { |
| *error_msg = "Missing file name"; |
| return false; |
| } |
| |
| // TODO: once added, use an api to android::base to read a std::vector<uint8_t>. |
| if (!android::base::ReadFileToString(filename.c_str(), &content)) { |
| *error_msg = "ReadFileToString failed for " + filename; |
| return false; |
| } |
| |
| const DexFileLoader dex_file_loader; |
| static constexpr bool kVerifyChecksum = true; |
| static constexpr bool kRunDexFileVerifier = true; |
| if (!dex_file_loader.OpenAll(reinterpret_cast<const uint8_t*>(content.data()), |
| content.size(), |
| filename.c_str(), |
| kRunDexFileVerifier, |
| kVerifyChecksum, |
| error_msg, |
| dex_files)) { |
| return false; |
| } |
| |
| return true; |
| } |
| }; |
| |
| } // namespace art |
| |
| int main(int argc, char** argv) { |
| return art::Veridex::Run(argc, argv); |
| } |
| |