Add image dependency to oat files
Change-Id: I945356f71357f1aa0092f4fe6c57eccfb029b4a6
diff --git a/src/class_linker.cc b/src/class_linker.cc
index c1acab0..f15d46f 100644
--- a/src/class_linker.cc
+++ b/src/class_linker.cc
@@ -736,6 +736,11 @@
if (oat_file.get() == NULL) {
return NULL;
}
+ Runtime* runtime = Runtime::Current();
+ const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
+ if (oat_file->GetOatHeader().GetImageFileLocationChecksum() != image_header.GetOatChecksum()) {
+ return NULL;
+ }
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
if (oat_dex_file == NULL) {
return NULL;
@@ -743,7 +748,7 @@
if (oat_dex_file->GetDexFileLocationChecksum() != dex_location_checksum) {
return NULL;
}
- Runtime::Current()->GetClassLinker()->RegisterOatFile(*oat_file.release());
+ runtime->GetClassLinker()->RegisterOatFile(*oat_file.release());
return oat_dex_file->OpenDexFile();
}
@@ -819,15 +824,33 @@
LOG(WARNING) << "Failed to compute checksum: " << dex_location;
return NULL;
}
+
+ Runtime* runtime = Runtime::Current();
+ const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
+ uint32_t image_checksum = image_header.GetOatChecksum();
+ bool image_check = (oat_file->GetOatHeader().GetImageFileLocationChecksum() == image_checksum);
+
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_location);
CHECK(oat_dex_file != NULL) << oat_filename << " " << dex_location;
- if (dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum()) {
+ bool dex_check = (dex_location_checksum == oat_dex_file->GetDexFileLocationChecksum());
+
+ if (image_check && dex_check) {
return oat_file->GetOatDexFile(dex_location)->OpenDexFile();
}
- LOG(WARNING) << ".oat file " << oat_file->GetLocation()
- << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
- << ") mismatch with " << dex_location
- << " (" << std::hex << dex_location_checksum << ")--- regenerating";
+ if (image_check) {
+ std::string image_file(image_header.GetImageRoot(
+ ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8());
+ LOG(WARNING) << ".oat file " << oat_file->GetLocation()
+ << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
+ << ") mismatch with " << image_file
+ << " (" << std::hex << image_checksum << ")--- regenerating";
+ }
+ if (dex_check) {
+ LOG(WARNING) << ".oat file " << oat_file->GetLocation()
+ << " checksum ( " << std::hex << oat_dex_file->GetDexFileLocationChecksum()
+ << ") mismatch with " << dex_location
+ << " (" << std::hex << dex_location_checksum << ")--- regenerating";
+ }
if (TEMP_FAILURE_RETRY(unlink(oat_file->GetLocation().c_str())) != 0) {
PLOG(FATAL) << "Couldn't remove obsolete .oat file " << oat_file->GetLocation();
}
@@ -874,6 +897,8 @@
ImageSpace* space = heap->GetImageSpace();
OatFile* oat_file = OpenOat(space);
CHECK(oat_file != NULL) << "Failed to open oat file for image";
+ CHECK_EQ(oat_file->GetOatHeader().GetImageFileLocationChecksum(), 0U);
+ CHECK(oat_file->GetOatHeader().GetImageFileLocation() == "");
Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
ObjectArray<DexCache>* dex_caches = dex_caches_object->AsObjectArray<DexCache>();
diff --git a/src/dalvik_system_DexFile.cc b/src/dalvik_system_DexFile.cc
index 2b86b76..2539c92 100644
--- a/src/dalvik_system_DexFile.cc
+++ b/src/dalvik_system_DexFile.cc
@@ -19,9 +19,11 @@
#include "class_loader.h"
#include "class_linker.h"
#include "dex_file.h"
+#include "image.h"
#include "logging.h"
#include "os.h"
#include "runtime.h"
+#include "space.h"
#include "zip_archive.h"
#include "toStringArray.h"
#include "ScopedLocalRef.h"
@@ -179,7 +181,8 @@
// Always treat elements of the bootclasspath as up-to-date. The
// fact that code is running at all means that this should be true.
- ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+ Runtime* runtime = Runtime::Current();
+ ClassLinker* class_linker = runtime->GetClassLinker();
const std::vector<const DexFile*>& boot_class_path = class_linker->GetBootClassPath();
for (size_t i = 0; i < boot_class_path.size(); i++) {
if (boot_class_path[i]->GetLocation() == filename.c_str()) {
@@ -211,6 +214,14 @@
return JNI_TRUE;
}
+ const ImageHeader& image_header = runtime->GetHeap()->GetImageSpace()->GetImageHeader();
+ if (oat_file->GetOatHeader().GetImageFileLocationChecksum() != image_header.GetOatChecksum()) {
+ LOG(INFO) << "DexFile_isDexOptNeeded cache file " << cache_location
+ << " has out-of-date checksum compared to "
+ << image_header.GetImageRoot(ImageHeader::kOatLocation)->AsString()->ToModifiedUtf8();
+ return JNI_TRUE;
+ }
+
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(filename.c_str());
if (oat_dex_file == NULL) {
LOG(ERROR) << "DexFile_isDexOptNeeded cache file " << cache_location
diff --git a/src/dex2oat.cc b/src/dex2oat.cc
index 1f02a44..f75aeb7 100644
--- a/src/dex2oat.cc
+++ b/src/dex2oat.cc
@@ -199,6 +199,7 @@
}
bool CreateOatFile(const std::string& boot_image_option,
+ const std::string& host_prefix,
const std::vector<const DexFile*>& dex_files,
File* oat_file,
#if defined(ART_USE_LLVM_COMPILER)
@@ -233,7 +234,24 @@
compiler.CompileAll(class_loader->get(), dex_files);
- if (!OatWriter::Create(oat_file, class_loader->get(), dex_files, compiler)) {
+ std::string image_file_location;
+ uint32_t image_file_location_checksum = 0;
+ Heap* heap = Runtime::Current()->GetHeap();
+ if (heap->GetSpaces().size() > 1) {
+ ImageSpace* image_space = heap->GetImageSpace();
+ image_file_location_checksum = image_space->GetImageHeader().GetOatChecksum();
+ image_file_location = image_space->GetImageFilename();
+ if (!host_prefix.empty() && StartsWith(image_file_location, host_prefix.c_str())) {
+ image_file_location = image_file_location.substr(host_prefix.size());
+ }
+ }
+
+ if (!OatWriter::Create(oat_file,
+ class_loader->get(),
+ dex_files,
+ image_file_location_checksum,
+ image_file_location,
+ compiler)) {
LOG(ERROR) << "Failed to create oat file " << oat_file->name();
return false;
}
@@ -687,6 +705,7 @@
}
if (!dex2oat->CreateOatFile(boot_image_option,
+ host_prefix,
dex_files,
oat_file.get(),
#if defined(ART_USE_LLVM_COMPILER)
diff --git a/src/image_test.cc b/src/image_test.cc
index fcea695..cf7c876 100644
--- a/src/image_test.cc
+++ b/src/image_test.cc
@@ -34,7 +34,7 @@
ScratchFile tmp_oat;
std::vector<const DexFile*> dex_files;
dex_files.push_back(java_lang_dex_file_);
- bool success_oat = OatWriter::Create(tmp_oat.GetFile(), NULL, dex_files, *compiler_.get());
+ bool success_oat = OatWriter::Create(tmp_oat.GetFile(), NULL, dex_files, 0, "", *compiler_.get());
ASSERT_TRUE(success_oat);
// Force all system classes into memory
diff --git a/src/oat.cc b/src/oat.cc
index e747a8b..d8d01df 100644
--- a/src/oat.cc
+++ b/src/oat.cc
@@ -27,14 +27,28 @@
memset(this, 0, sizeof(*this));
}
-OatHeader::OatHeader(InstructionSet instruction_set, const std::vector<const DexFile*>* dex_files) {
+OatHeader::OatHeader(InstructionSet instruction_set,
+ const std::vector<const DexFile*>* dex_files,
+ uint32_t image_file_location_checksum,
+ const std::string& image_file_location) {
memcpy(magic_, kOatMagic, sizeof(kOatMagic));
memcpy(version_, kOatVersion, sizeof(kOatVersion));
+
adler32_checksum_ = adler32(0L, Z_NULL, 0);
+
instruction_set_ = instruction_set;
UpdateChecksum(&instruction_set_, sizeof(instruction_set_));
+
dex_file_count_ = dex_files->size();
UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_));
+
+ image_file_location_checksum_ = image_file_location_checksum;
+ UpdateChecksum(&image_file_location_checksum_, sizeof(image_file_location_checksum_));
+
+ image_file_location_size_ = image_file_location.size();
+ UpdateChecksum(&image_file_location_size_, sizeof(image_file_location_size_));
+ UpdateChecksum(image_file_location.data(), image_file_location_size_);
+
executable_offset_ = 0;
}
@@ -81,11 +95,33 @@
return executable_offset_;
}
+uint32_t OatHeader::GetImageFileLocationChecksum() const {
+ CHECK(IsValid());
+ return image_file_location_checksum_;
+}
+
+uint32_t OatHeader::GetImageFileLocationSize() const {
+ CHECK(IsValid());
+ return image_file_location_size_;
+}
+
+const uint8_t* OatHeader::GetImageFileLocationData() const {
+ CHECK(IsValid());
+ return image_file_location_data_;
+}
+
+std::string OatHeader::GetImageFileLocation() const {
+ CHECK(IsValid());
+ return std::string(reinterpret_cast<const char*>(GetImageFileLocationData()),
+ GetImageFileLocationSize());
+}
+
void OatHeader::SetExecutableOffset(uint32_t executable_offset) {
DCHECK_ALIGNED(executable_offset, kPageSize);
CHECK_GT(executable_offset, sizeof(OatHeader));
DCHECK(IsValid());
DCHECK_EQ(executable_offset_, 0U);
+
executable_offset_ = executable_offset;
UpdateChecksum(&executable_offset_, sizeof(executable_offset));
}
diff --git a/src/oat.h b/src/oat.h
index 2f3cf9d..25a4373 100644
--- a/src/oat.h
+++ b/src/oat.h
@@ -28,7 +28,10 @@
class PACKED OatHeader {
public:
OatHeader();
- OatHeader(InstructionSet instruction_set, const std::vector<const DexFile*>* dex_files);
+ OatHeader(InstructionSet instruction_set,
+ const std::vector<const DexFile*>* dex_files,
+ uint32_t image_file_location_checksum,
+ const std::string& image_file_location);
bool IsValid() const;
const char* GetMagic() const;
@@ -38,6 +41,10 @@
uint32_t GetExecutableOffset() const;
InstructionSet GetInstructionSet() const;
void SetExecutableOffset(uint32_t executable_offset);
+ uint32_t GetImageFileLocationChecksum() const;
+ uint32_t GetImageFileLocationSize() const;
+ const uint8_t* GetImageFileLocationData() const;
+ std::string GetImageFileLocation() const;
private:
static const uint8_t kOatMagic[4];
@@ -51,6 +58,10 @@
uint32_t dex_file_count_;
uint32_t executable_offset_;
+ uint32_t image_file_location_checksum_;
+ uint32_t image_file_location_size_;
+ uint8_t image_file_location_data_[0]; // note variable width data at end
+
DISALLOW_COPY_AND_ASSIGN(OatHeader);
};
diff --git a/src/oat_file.cc b/src/oat_file.cc
index f0c004d..e72944e 100644
--- a/src/oat_file.cc
+++ b/src/oat_file.cc
@@ -101,7 +101,14 @@
const byte* oat = map->Begin();
oat += sizeof(OatHeader);
- CHECK_LE(oat, map->End()) << GetLocation();
+ oat += oat_header.GetImageFileLocationSize();
+
+ CHECK_LE(oat, map->End())
+ << reinterpret_cast<void*>(map->Begin())
+ << "+" << sizeof(OatHeader)
+ << "+" << oat_header.GetImageFileLocationSize()
+ << "<=" << reinterpret_cast<void*>(map->End())
+ << " " << GetLocation();
for (size_t i = 0; i < oat_header.GetDexFileCount(); i++) {
size_t dex_file_location_size = *reinterpret_cast<const uint32_t*>(oat);
CHECK_GT(dex_file_location_size, 0U) << GetLocation();
diff --git a/src/oat_test.cc b/src/oat_test.cc
index 0ca581a..3cbd3ed 100644
--- a/src/oat_test.cc
+++ b/src/oat_test.cc
@@ -34,7 +34,12 @@
}
ScratchFile tmp;
- bool success = OatWriter::Create(tmp.GetFile(), class_loader.get(), class_linker->GetBootClassPath(), *compiler_.get());
+ bool success = OatWriter::Create(tmp.GetFile(),
+ class_loader.get(),
+ class_linker->GetBootClassPath(),
+ 42U,
+ "lue.art",
+ *compiler_.get());
ASSERT_TRUE(success);
if (compile) { // OatWriter strips the code, regenerate to compare
@@ -44,6 +49,8 @@
ASSERT_TRUE(oat_file.get() != NULL);
const OatHeader& oat_header = oat_file->GetOatHeader();
ASSERT_EQ(1U, oat_header.GetDexFileCount());
+ ASSERT_EQ(42U, oat_header.GetImageFileLocationChecksum());
+ ASSERT_EQ("lue.art", oat_header.GetImageFileLocation());
const DexFile* dex_file = java_lang_dex_file_;
const OatFile::OatDexFile* oat_dex_file = oat_file->GetOatDexFile(dex_file->GetLocation());
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index a1b0f9d..8e127deb 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -20,6 +20,7 @@
#include "class_loader.h"
#include "file.h"
#include "os.h"
+#include "space.h"
#include "stl_util.h"
namespace art {
@@ -27,21 +28,31 @@
bool OatWriter::Create(File* file,
const ClassLoader* class_loader,
const std::vector<const DexFile*>& dex_files,
+ uint32_t image_file_location_checksum,
+ const std::string& image_file_location,
const Compiler& compiler) {
- OatWriter oat_writer(dex_files, class_loader, compiler);
+ OatWriter oat_writer(dex_files,
+ image_file_location_checksum,
+ image_file_location,
+ class_loader,
+ compiler);
return oat_writer.Write(file);
}
OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files,
+ uint32_t image_file_location_checksum,
+ const std::string& image_file_location,
const ClassLoader* class_loader,
const Compiler& compiler) {
compiler_ = &compiler;
class_loader_ = class_loader;
+ image_file_location_checksum_ = image_file_location_checksum;
+ image_file_location_ = image_file_location;
dex_files_ = &dex_files;
oat_header_ = NULL;
executable_offset_padding_length_ = 0;
- size_t offset = InitOatHeader(compiler.GetInstructionSet());
+ size_t offset = InitOatHeader();
offset = InitOatDexFiles(offset);
offset = InitDexFiles(offset);
offset = InitOatClasses(offset);
@@ -57,10 +68,14 @@
STLDeleteElements(&oat_classes_);
}
-size_t OatWriter::InitOatHeader(InstructionSet instruction_set) {
+size_t OatWriter::InitOatHeader() {
// create the OatHeader
- oat_header_ = new OatHeader(instruction_set, dex_files_);
+ oat_header_ = new OatHeader(compiler_->GetInstructionSet(),
+ dex_files_,
+ image_file_location_checksum_,
+ image_file_location_);
size_t offset = sizeof(*oat_header_);
+ offset += image_file_location_.size();
return offset;
}
@@ -361,6 +376,12 @@
return false;
}
+ if (!file->WriteFully(image_file_location_.data(),
+ image_file_location_.size())) {
+ PLOG(ERROR) << "Failed to write oat header image file location to " << file->name();
+ return false;
+ }
+
if (!WriteTables(file)) {
LOG(ERROR) << "Failed to write oat tables to " << file->name();
return false;
diff --git a/src/oat_writer.h b/src/oat_writer.h
index 210a659..c3a8ff6 100644
--- a/src/oat_writer.h
+++ b/src/oat_writer.h
@@ -28,11 +28,10 @@
#include "oat.h"
#include "object.h"
#include "os.h"
-#include "space.h"
namespace art {
-// OatHeader fixed length with count of D OatDexFiles
+// OatHeader variable length with count of D OatDexFiles
//
// OatDexFile[0] one variable sized OatDexFile with offsets to Dex and OatClasses
// OatDexFile[1]
@@ -63,17 +62,23 @@
class OatWriter {
public:
// Write an oat file. Returns true on success, false on failure.
- static bool Create(File* file, const ClassLoader* class_loader,
- const std::vector<const DexFile*>& dex_files, const Compiler& compiler);
+ static bool Create(File* file,
+ const ClassLoader* class_loader,
+ const std::vector<const DexFile*>& dex_files,
+ uint32_t image_file_location_checksum,
+ const std::string& image_file_location,
+ const Compiler& compiler);
private:
OatWriter(const std::vector<const DexFile*>& dex_files,
+ uint32_t image_file_location_checksum,
+ const std::string& image_file_location,
const ClassLoader* class_loader,
const Compiler& compiler);
~OatWriter();
- size_t InitOatHeader(InstructionSet instruction_set);
+ size_t InitOatHeader();
size_t InitOatDexFiles(size_t offset);
size_t InitDexFiles(size_t offset);
size_t InitOatClasses(size_t offset);
@@ -146,6 +151,10 @@
// note OatFile does not take ownership of the DexFiles
const std::vector<const DexFile*>* dex_files_;
+ // dependency on the image
+ uint32_t image_file_location_checksum_;
+ std::string image_file_location_;
+
// data to write
OatHeader* oat_header_;
std::vector<OatDexFile*> oat_dex_files_;
diff --git a/src/oatdump.cc b/src/oatdump.cc
index 295c74f..ae0ad57 100644
--- a/src/oatdump.cc
+++ b/src/oatdump.cc
@@ -85,7 +85,9 @@
class OatDumper {
public:
- explicit OatDumper(const OatFile& oat_file) : oat_file_(oat_file),
+ explicit OatDumper(const std::string& host_prefix, const OatFile& oat_file)
+ : host_prefix_(host_prefix),
+ oat_file_(oat_file),
oat_dex_files_(oat_file.GetOatDexFiles()),
disassembler_(Disassembler::Create(oat_file_.GetOatHeader().GetInstructionSet())) {
AddAllOffsets();
@@ -109,6 +111,17 @@
os << "EXECUTABLE OFFSET:\n";
os << StringPrintf("0x%08x\n\n", oat_header.GetExecutableOffset());
+ os << "IMAGE FILE LOCATION CHECKSUM:\n";
+ os << StringPrintf("0x%08x\n\n", oat_header.GetImageFileLocationChecksum());
+
+ os << "IMAGE FILE LOCATION:\n";
+ const std::string image_file_location(oat_header.GetImageFileLocation());
+ os << image_file_location;
+ if (!image_file_location.empty() && !host_prefix_.empty()) {
+ os << " (" << host_prefix_ << image_file_location << ")";
+ }
+ os << "\n\n";
+
os << "BEGIN:\n";
os << reinterpret_cast<const void*>(oat_file_.Begin()) << "\n\n";
@@ -470,6 +483,7 @@
}
}
+ const std::string host_prefix_;
const OatFile& oat_file_;
std::vector<const OatFile::OatDexFile*> oat_dex_files_;
std::set<uint32_t> offsets_;
@@ -548,7 +562,7 @@
stats_.oat_file_bytes = oat_file->Size();
- oat_dumper_.reset(new OatDumper(*oat_file));
+ oat_dumper_.reset(new OatDumper(host_prefix_, *oat_file));
os_ << "OBJECTS:\n" << std::flush;
HeapBitmap* heap_bitmap = Runtime::Current()->GetHeap()->GetLiveBits();
@@ -1110,13 +1124,20 @@
return EXIT_FAILURE;
}
+ if (host_prefix.empty()) {
+ const char* android_product_out = getenv("ANDROID_PRODUCT_OUT");
+ if (android_product_out != NULL) {
+ host_prefix = android_product_out;
+ }
+ }
+
if (oat_filename != NULL) {
OatFile* oat_file = OatFile::Open(oat_filename, oat_filename, NULL);
if (oat_file == NULL) {
fprintf(stderr, "Failed to open oat file from %s\n", oat_filename);
return EXIT_FAILURE;
}
- OatDumper oat_dumper(*oat_file);
+ OatDumper oat_dumper(host_prefix, *oat_file);
oat_dumper.Dump(*os);
return EXIT_SUCCESS;
}
@@ -1137,12 +1158,6 @@
options.push_back(std::make_pair(image_option.c_str(), reinterpret_cast<void*>(NULL)));
}
- if (host_prefix.empty()) {
- const char* android_product_out = getenv("ANDROID_PRODUCT_OUT");
- if (android_product_out != NULL) {
- host_prefix = android_product_out;
- }
- }
if (!host_prefix.empty()) {
options.push_back(std::make_pair("host-prefix", host_prefix.c_str()));
}