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);
+}
+