Merge "Add veridex project."
diff --git a/tools/veridex/Android.bp b/tools/veridex/Android.bp
new file mode 100644
index 0000000..cac441a
--- /dev/null
+++ b/tools/veridex/Android.bp
@@ -0,0 +1,24 @@
+// 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.
+
+art_cc_binary {
+ name: "veridex",
+ host_supported: true,
+ srcs: ["veridex.cc"],
+ cflags: ["-Wall", "-Werror"],
+ shared_libs: ["libdexfile", "libbase"],
+ header_libs: [
+ "art_libartbase_headers",
+ ],
+}
diff --git a/tools/veridex/veridex.cc b/tools/veridex/veridex.cc
new file mode 100644
index 0000000..9d0dd36
--- /dev/null
+++ b/tools/veridex/veridex.cc
@@ -0,0 +1,152 @@
+/*
+ * 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);
+}
+