summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author David Srbecky <dsrbecky@google.com> 2019-02-27 15:10:52 +0000
committer David Srbecky <dsrbecky@google.com> 2019-03-22 18:22:34 +0000
commite5d93b58a530be39c9a067cdd7f491e4626ec51d (patch)
tree30becd07985c4c2f7b2a339f7d6783220255f08e
parent336245d020ce5d1595c56a2953bf7b3103b54984 (diff)
Compare the oat version of runtime, dex2oat and the compiler.
Ensure they match, otherwise we might get confusing crashes. Bug: 125318570 Test: running ahat-test-dump after oat version bump triggers the check. Change-Id: If4bc832af50c2cb851054be03c9887f9a3d4d04b
-rw-r--r--compiler/compiler.cc4
-rw-r--r--dex2oat/linker/oat_writer.cc4
-rw-r--r--runtime/oat.cc27
-rw-r--r--runtime/oat.h10
4 files changed, 32 insertions, 13 deletions
diff --git a/compiler/compiler.cc b/compiler/compiler.cc
index d044c2fe4f..98d73396bc 100644
--- a/compiler/compiler.cc
+++ b/compiler/compiler.cc
@@ -22,6 +22,7 @@
#include "base/utils.h"
#include "dex/code_item_accessors-inl.h"
#include "dex/dex_file.h"
+#include "oat.h"
#include "optimizing/optimizing_compiler.h"
namespace art {
@@ -29,6 +30,9 @@ namespace art {
Compiler* Compiler::Create(const CompilerOptions& compiler_options,
CompiledMethodStorage* storage,
Compiler::Kind kind) {
+ // Check that oat version when runtime was compiled matches the oat version of the compiler.
+ constexpr std::array<uint8_t, 4> compiler_oat_version = OatHeader::kOatVersion;
+ OatHeader::CheckOatVersion(compiler_oat_version);
switch (kind) {
case kQuick:
// TODO: Remove Quick in options.
diff --git a/dex2oat/linker/oat_writer.cc b/dex2oat/linker/oat_writer.cc
index 897278f6c8..c39217709e 100644
--- a/dex2oat/linker/oat_writer.cc
+++ b/dex2oat/linker/oat_writer.cc
@@ -2011,6 +2011,10 @@ bool OatWriter::VisitDexMethods(DexMethodVisitor* visitor) {
size_t OatWriter::InitOatHeader(uint32_t num_dex_files,
SafeMap<std::string, std::string>* key_value_store) {
TimingLogger::ScopedTiming split("InitOatHeader", timings_);
+ // Check that oat version when runtime was compiled matches the oat version
+ // when dex2oat was compiled. We have seen cases where they got out of sync.
+ constexpr std::array<uint8_t, 4> dex2oat_oat_version = OatHeader::kOatVersion;
+ OatHeader::CheckOatVersion(dex2oat_oat_version);
oat_header_.reset(OatHeader::Create(GetCompilerOptions().GetInstructionSet(),
GetCompilerOptions().GetInstructionSetFeatures(),
num_dex_files,
diff --git a/runtime/oat.cc b/runtime/oat.cc
index b8289876a8..db6cda5027 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -29,8 +29,6 @@ namespace art {
using android::base::StringPrintf;
-constexpr uint8_t OatHeader::kOatMagic[4];
-constexpr uint8_t OatHeader::kOatVersion[4];
constexpr const char OatHeader::kTrueValue[];
constexpr const char OatHeader::kFalseValue[];
@@ -86,8 +84,8 @@ OatHeader::OatHeader(InstructionSet instruction_set,
static_assert(sizeof(version_) == sizeof(kOatVersion),
"Oat version and version_ have different lengths.");
- memcpy(magic_, kOatMagic, sizeof(kOatMagic));
- memcpy(version_, kOatVersion, sizeof(kOatVersion));
+ magic_ = kOatMagic;
+ version_ = kOatVersion;
CHECK_NE(instruction_set, InstructionSet::kNone);
@@ -96,10 +94,10 @@ OatHeader::OatHeader(InstructionSet instruction_set,
}
bool OatHeader::IsValid() const {
- if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
+ if (magic_ != kOatMagic) {
return false;
}
- if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
+ if (version_ != kOatVersion) {
return false;
}
if (!IsAligned<kPageSize>(executable_offset_)) {
@@ -112,13 +110,13 @@ bool OatHeader::IsValid() const {
}
std::string OatHeader::GetValidationErrorMessage() const {
- if (memcmp(magic_, kOatMagic, sizeof(kOatMagic)) != 0) {
+ if (magic_ != kOatMagic) {
static_assert(sizeof(kOatMagic) == 4, "kOatMagic has unexpected length");
return StringPrintf("Invalid oat magic, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
kOatMagic[0], kOatMagic[1], kOatMagic[2], kOatMagic[3],
magic_[0], magic_[1], magic_[2], magic_[3]);
}
- if (memcmp(version_, kOatVersion, sizeof(kOatVersion)) != 0) {
+ if (version_ != kOatVersion) {
static_assert(sizeof(kOatVersion) == 4, "kOatVersion has unexpected length");
return StringPrintf("Invalid oat version, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
kOatVersion[0], kOatVersion[1], kOatVersion[2], kOatVersion[3],
@@ -133,9 +131,20 @@ std::string OatHeader::GetValidationErrorMessage() const {
return "";
}
+// Do not move this into the header. The method must be compiled in the runtime library,
+// so that we can check that the compile-time oat version matches the version in the caller.
+void OatHeader::CheckOatVersion(std::array<uint8_t, 4> version) {
+ constexpr std::array<uint8_t, 4> expected = kOatVersion; // Runtime oat version.
+ if (version != kOatVersion) {
+ LOG(FATAL) << StringPrintf("Invalid oat version, expected 0x%x%x%x%x, got 0x%x%x%x%x.",
+ expected[0], expected[1], expected[2], expected[3],
+ version[0], version[1], version[2], version[3]);
+ }
+}
+
const char* OatHeader::GetMagic() const {
CHECK(IsValid());
- return reinterpret_cast<const char*>(magic_);
+ return reinterpret_cast<const char*>(magic_.data());
}
uint32_t OatHeader::GetChecksum() const {
diff --git a/runtime/oat.h b/runtime/oat.h
index 3877f3eeb5..15059a8a96 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -17,6 +17,7 @@
#ifndef ART_RUNTIME_OAT_H_
#define ART_RUNTIME_OAT_H_
+#include <array>
#include <vector>
#include "base/macros.h"
@@ -30,9 +31,9 @@ class InstructionSetFeatures;
class PACKED(4) OatHeader {
public:
- static constexpr uint8_t kOatMagic[] = { 'o', 'a', 't', '\n' };
+ static constexpr std::array<uint8_t, 4> kOatMagic { { 'o', 'a', 't', '\n' } };
// Last oat version changed reason: Remove unused trampoline entrypoints.
- static constexpr uint8_t kOatVersion[] = { '1', '7', '0', '\0' };
+ static constexpr std::array<uint8_t, 4> kOatVersion { { '1', '7', '0', '\0' } };
static constexpr const char* kDex2OatCmdLineKey = "dex2oat-cmdline";
static constexpr const char* kDebuggableKey = "debuggable";
@@ -55,6 +56,7 @@ class PACKED(4) OatHeader {
bool IsValid() const;
std::string GetValidationErrorMessage() const;
+ static void CheckOatVersion(std::array<uint8_t, 4> version);
const char* GetMagic() const;
uint32_t GetChecksum() const;
void SetChecksum(uint32_t checksum);
@@ -111,8 +113,8 @@ class PACKED(4) OatHeader {
void Flatten(const SafeMap<std::string, std::string>* variable_data);
- uint8_t magic_[4];
- uint8_t version_[4];
+ std::array<uint8_t, 4> magic_;
+ std::array<uint8_t, 4> version_;
uint32_t oat_checksum_;
InstructionSet instruction_set_;