Add resolver to veridex.

Resolver runs over dex file and cache classes/methods/fields.

Change-Id: I0574891cd72b5aa72f97784c6391912fa8ed8c1c
diff --git a/tools/veridex/Android.bp b/tools/veridex/Android.bp
index cac441a..31ff682 100644
--- a/tools/veridex/Android.bp
+++ b/tools/veridex/Android.bp
@@ -15,7 +15,10 @@
 art_cc_binary {
     name: "veridex",
     host_supported: true,
-    srcs: ["veridex.cc"],
+    srcs: [
+        "resolver.cc",
+        "veridex.cc",
+    ],
     cflags: ["-Wall", "-Werror"],
     shared_libs: ["libdexfile", "libbase"],
     header_libs: [
diff --git a/tools/veridex/resolver.cc b/tools/veridex/resolver.cc
new file mode 100644
index 0000000..c0705e5
--- /dev/null
+++ b/tools/veridex/resolver.cc
@@ -0,0 +1,58 @@
+/*
+ * 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 "resolver.h"
+
+#include "dex/dex_file-inl.h"
+#include "dex/primitive.h"
+#include "veridex.h"
+
+namespace art {
+
+void VeridexResolver::Run() {
+  size_t class_def_count = dex_file_.NumClassDefs();
+  for (size_t class_def_index = 0; class_def_index < class_def_count; ++class_def_index) {
+    const DexFile::ClassDef& class_def = dex_file_.GetClassDef(class_def_index);
+    std::string name(dex_file_.StringByTypeIdx(class_def.class_idx_));
+    auto existing = type_map_.find(name);
+    if (existing != type_map_.end()) {
+      // Class already exists, cache it and move on.
+      type_infos_[class_def.class_idx_.index_] = *existing->second;
+      continue;
+    }
+    type_infos_[class_def.class_idx_.index_] = VeriClass(Primitive::Type::kPrimNot, 0, &class_def);
+    type_map_[name] = &(type_infos_[class_def.class_idx_.index_]);
+
+    const uint8_t* class_data = dex_file_.GetClassData(class_def);
+    if (class_data == nullptr) {
+      // Empty class.
+      continue;
+    }
+
+    ClassDataItemIterator it(dex_file_, class_data);
+    for (; it.HasNextStaticField(); it.Next()) {
+      field_infos_[it.GetMemberIndex()] = it.DataPointer();
+    }
+    for (; it.HasNextInstanceField(); it.Next()) {
+      field_infos_[it.GetMemberIndex()] = it.DataPointer();
+    }
+    for (; it.HasNextMethod(); it.Next()) {
+      method_infos_[it.GetMemberIndex()] = it.DataPointer();
+    }
+  }
+}
+
+}  // namespace art
diff --git a/tools/veridex/resolver.h b/tools/veridex/resolver.h
new file mode 100644
index 0000000..4e0c5b3
--- /dev/null
+++ b/tools/veridex/resolver.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_TOOLS_VERIDEX_RESOLVER_H_
+#define ART_TOOLS_VERIDEX_RESOLVER_H_
+
+#include "dex/dex_file.h"
+#include "veridex.h"
+
+namespace art {
+
+class VeridexResolver {
+ public:
+  VeridexResolver(const DexFile& dex_file, TypeMap& type_map)
+      : dex_file_(dex_file),
+        type_map_(type_map),
+        type_infos_(dex_file.NumTypeIds(), VeriClass()),
+        method_infos_(dex_file.NumMethodIds(), nullptr),
+        field_infos_(dex_file.NumFieldIds(), nullptr) {}
+
+  void Run();
+
+ private:
+  const DexFile& dex_file_;
+  TypeMap& type_map_;
+  std::vector<VeriClass> type_infos_;
+  std::vector<VeriMethod> method_infos_;
+  std::vector<VeriField> field_infos_;
+};
+
+}  // namespace art
+
+#endif  // ART_TOOLS_VERIDEX_RESOLVER_H_
diff --git a/tools/veridex/veridex.cc b/tools/veridex/veridex.cc
index 9d0dd36..0370a03 100644
--- a/tools/veridex/veridex.cc
+++ b/tools/veridex/veridex.cc
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
+#include "veridex.h"
+
 #include <android-base/file.h>
 
 #include "dex/dex_file.h"
 #include "dex/dex_file_loader.h"
+#include "resolver.h"
 
 #include <sstream>
 
@@ -108,6 +111,18 @@
         return 1;
       }
     }
+
+    // Resolve classes/methods/fields defined in each dex file.
+
+    // Cache of types we've seen. This is used in case of duplicate classes.
+    TypeMap type_map;
+
+    std::vector<VeridexResolver> boot_resolvers;
+    Resolve(boot_dex_files, type_map, &boot_resolvers);
+
+    std::vector<VeridexResolver> app_resolvers;
+    Resolve(app_dex_files, type_map, &app_resolvers);
+
     return 0;
   }
 
@@ -142,6 +157,18 @@
 
     return true;
   }
+
+  static void Resolve(const std::vector<std::unique_ptr<const DexFile>>& dex_files,
+                      TypeMap& type_map,
+                      std::vector<VeridexResolver>* resolvers) {
+    for (const std::unique_ptr<const DexFile>& dex_file : dex_files) {
+      resolvers->push_back(VeridexResolver(*dex_file.get(), type_map));
+    }
+
+    for (VeridexResolver& resolver : *resolvers) {
+      resolver.Run();
+    }
+  }
 };
 
 }  // namespace art
diff --git a/tools/veridex/veridex.h b/tools/veridex/veridex.h
new file mode 100644
index 0000000..bbff254
--- /dev/null
+++ b/tools/veridex/veridex.h
@@ -0,0 +1,72 @@
+/*
+ * 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.
+ */
+
+#ifndef ART_TOOLS_VERIDEX_VERIDEX_H_
+#define ART_TOOLS_VERIDEX_VERIDEX_H_
+
+#include <map>
+
+#include "dex/dex_file.h"
+#include "dex/primitive.h"
+
+namespace art {
+
+/**
+ * Abstraction for classes defined, or implicitly defined (for arrays and primitives)
+ * in dex files.
+ */
+class VeriClass {
+ public:
+  VeriClass(const VeriClass& other) = default;
+  VeriClass() = default;
+  VeriClass(Primitive::Type k, uint8_t dims, const DexFile::ClassDef* cl)
+      : kind_(k), dimensions_(dims), class_def_(cl) {}
+
+  bool IsUninitialized() const {
+    return kind_ == Primitive::Type::kPrimNot && dimensions_ == 0 && class_def_ == nullptr;
+  }
+
+  bool IsPrimitive() const {
+    return kind_ != Primitive::Type::kPrimNot && dimensions_ == 0;
+  }
+
+  bool IsArray() const {
+    return dimensions_ != 0;
+  }
+
+ private:
+  Primitive::Type kind_;
+  uint8_t dimensions_;
+  const DexFile::ClassDef* class_def_;
+};
+
+/**
+ * Abstraction for fields defined in dex files. Currently, that's a pointer into their
+ * `encoded_field` description.
+ */
+using VeriField = const uint8_t*;
+
+/**
+ * Abstraction for methods defined in dex files. Currently, that's a pointer into their
+ * `encoded_method` description.
+ */
+using VeriMethod = const uint8_t*;
+
+using TypeMap = std::map<std::string, VeriClass*>;
+
+}  // namespace art
+
+#endif  // ART_TOOLS_VERIDEX_VERIDEX_H_