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_