Dump VerifierDeps in oatdump.
bug:30937355
test: oatdump_test
Change-Id: I344726a20f21a6c6986047c21278c753b9e24575
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index cd6ca4c..3a53998 100644
--- a/compiler/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -1076,7 +1076,7 @@
verifier_deps_->Encode(dex_files_, &buffer);
ASSERT_FALSE(buffer.empty());
- VerifierDeps decoded_deps(dex_files_, ArrayRef<uint8_t>(buffer));
+ VerifierDeps decoded_deps(dex_files_, ArrayRef<const uint8_t>(buffer));
ASSERT_TRUE(verifier_deps_->Equals(decoded_deps));
}
@@ -1102,7 +1102,7 @@
}
// Dump the new verifier deps to ensure it can properly read the data.
- VerifierDeps decoded_deps(dex_files, ArrayRef<uint8_t>(buffer));
+ VerifierDeps decoded_deps(dex_files, ArrayRef<const uint8_t>(buffer));
std::ostringstream stream;
VariableIndentationOutputStream os(&stream);
decoded_deps.Dump(&os);
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index da0db01..3d208b5 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -66,6 +66,7 @@
#include "type_lookup_table.h"
#include "vdex_file.h"
#include "verifier/method_verifier.h"
+#include "verifier/verifier_deps.h"
#include "well_known_classes.h"
#include <sys/stat.h>
@@ -483,6 +484,28 @@
os << "\n";
if (!options_.dump_header_only_) {
+ VariableIndentationOutputStream vios(&os);
+ VdexFile::Header vdex_header = oat_file_.GetVdexFile()->GetHeader();
+ if (vdex_header.IsValid()) {
+ std::string error_msg;
+ std::vector<const DexFile*> dex_files;
+ for (size_t i = 0; i < oat_dex_files_.size(); i++) {
+ const DexFile* dex_file = OpenDexFile(oat_dex_files_[i], &error_msg);
+ if (dex_file == nullptr) {
+ os << "Error opening dex file: " << error_msg << std::endl;
+ return false;
+ }
+ dex_files.push_back(dex_file);
+ }
+ verifier::VerifierDeps deps(dex_files, oat_file_.GetVdexFile()->GetVerifierDepsData());
+ deps.Dump(&vios);
+ } else {
+ os << "UNRECOGNIZED vdex file, magic "
+ << vdex_header.GetMagic()
+ << ", version "
+ << vdex_header.GetVersion()
+ << "\n";
+ }
for (size_t i = 0; i < oat_dex_files_.size(); i++) {
const OatFile::OatDexFile* oat_dex_file = oat_dex_files_[i];
CHECK(oat_dex_file != nullptr);
diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h
index 28f9bb3..edd6ffe 100644
--- a/runtime/vdex_file.h
+++ b/runtime/vdex_file.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <string>
+#include "base/array_ref.h"
#include "base/macros.h"
#include "mem_map.h"
#include "os.h"
@@ -44,8 +45,11 @@
public:
Header(uint32_t dex_size, uint32_t verifier_deps_size, uint32_t quickening_info_size);
+ const char* GetMagic() const { return reinterpret_cast<const char*>(magic_); }
+ const char* GetVersion() const { return reinterpret_cast<const char*>(version_); }
bool IsMagicValid() const;
bool IsVersionValid() const;
+ bool IsValid() const { return IsMagicValid() && IsVersionValid(); }
uint32_t GetDexSize() const { return dex_size_; }
uint32_t GetVerifierDepsSize() const { return verifier_deps_size_; }
@@ -71,6 +75,15 @@
const uint8_t* End() const { return mmap_->End(); }
size_t Size() const { return mmap_->Size(); }
+ const Header& GetHeader() const {
+ return *reinterpret_cast<const Header*>(Begin());
+ }
+
+ ArrayRef<const uint8_t> GetVerifierDepsData() const {
+ return ArrayRef<const uint8_t>(
+ Begin() + sizeof(Header) + GetHeader().GetDexSize(), GetHeader().GetVerifierDepsSize());
+ }
+
private:
explicit VdexFile(MemMap* mmap) : mmap_(mmap) {}
diff --git a/runtime/verifier/verifier_deps.cc b/runtime/verifier/verifier_deps.cc
index 6970871..149861c 100644
--- a/runtime/verifier/verifier_deps.cc
+++ b/runtime/verifier/verifier_deps.cc
@@ -453,8 +453,15 @@
}
}
-VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files, ArrayRef<uint8_t> data)
+VerifierDeps::VerifierDeps(const std::vector<const DexFile*>& dex_files,
+ ArrayRef<const uint8_t> data)
: VerifierDeps(dex_files) {
+ if (data.empty()) {
+ // Return eagerly, as the first thing we expect from VerifierDeps data is
+ // the number of created strings, even if there is no dependency.
+ // Currently, only the boot image does not have any VerifierDeps data.
+ return;
+ }
const uint8_t* data_start = data.data();
const uint8_t* data_end = data_start + data.size();
for (const DexFile* dex_file : dex_files) {
diff --git a/runtime/verifier/verifier_deps.h b/runtime/verifier/verifier_deps.h
index 6b0c959..fab4323 100644
--- a/runtime/verifier/verifier_deps.h
+++ b/runtime/verifier/verifier_deps.h
@@ -51,6 +51,10 @@
explicit VerifierDeps(const std::vector<const DexFile*>& dex_files)
REQUIRES(!Locks::verifier_deps_lock_);
+ VerifierDeps(const std::vector<const DexFile*>& dex_files,
+ ArrayRef<const uint8_t> data)
+ REQUIRES(!Locks::verifier_deps_lock_);
+
// Record the verification status of the class at `type_idx`.
static void MaybeRecordVerificationStatus(const DexFile& dex_file,
uint16_t type_idx,
@@ -108,10 +112,6 @@
private:
static constexpr uint16_t kUnresolvedMarker = static_cast<uint16_t>(-1);
- // Only used in tests to reconstruct the data structure from serialized data.
- VerifierDeps(const std::vector<const DexFile*>& dex_files, ArrayRef<uint8_t> data)
- REQUIRES(!Locks::verifier_deps_lock_);
-
using ClassResolutionBase = std::tuple<uint32_t, uint16_t>;
struct ClassResolution : public ClassResolutionBase {
ClassResolution() = default;