diff options
author | Logan Chien <loganchien@google.com> | 2012-03-20 20:19:26 +0800 |
---|---|---|
committer | Shih-wei Liao <sliao@google.com> | 2012-03-26 21:09:55 -0700 |
commit | 25ae64082c2583a080b9d0bd005d2efd09e81723 (patch) | |
tree | 59a129ce418ff6484f569cac74382b959d978cbd | |
parent | df57614aa99801a50202e284ee8e8497d8e92621 (diff) | |
download | art-25ae64082c2583a080b9d0bd005d2efd09e81723.zip art-25ae64082c2583a080b9d0bd005d2efd09e81723.tar.gz art-25ae64082c2583a080b9d0bd005d2efd09e81723.tar.bz2 |
Write ELF image to Oat file.
(cherry picked from commit 1c84f1fd7570974bec8660cd17e0118be529afce)
Change-Id: I322579095009a09ab9ad8d2e7d7c309a5530718c
-rw-r--r-- | src/oat.cc | 21 | ||||
-rw-r--r-- | src/oat.h | 6 | ||||
-rw-r--r-- | src/oat_writer.cc | 94 | ||||
-rw-r--r-- | src/oat_writer.h | 34 |
4 files changed, 155 insertions, 0 deletions
@@ -29,6 +29,7 @@ OatHeader::OatHeader() { OatHeader::OatHeader(InstructionSet instruction_set, const std::vector<const DexFile*>* dex_files, + uint32_t elf_image_count, uint32_t image_file_location_checksum, const std::string& image_file_location) { memcpy(magic_, kOatMagic, sizeof(kOatMagic)); @@ -42,6 +43,9 @@ OatHeader::OatHeader(InstructionSet instruction_set, dex_file_count_ = dex_files->size(); UpdateChecksum(&dex_file_count_, sizeof(dex_file_count_)); + elf_image_count_ = elf_image_count; + UpdateChecksum(&elf_image_count_, sizeof(elf_image_count_)); + image_file_location_checksum_ = image_file_location_checksum; UpdateChecksum(&image_file_location_checksum_, sizeof(image_file_location_checksum_)); @@ -49,6 +53,7 @@ OatHeader::OatHeader(InstructionSet instruction_set, UpdateChecksum(&image_file_location_size_, sizeof(image_file_location_size_)); UpdateChecksum(image_file_location.data(), image_file_location_size_); + elf_image_table_offset_ = 0; executable_offset_ = 0; } @@ -72,6 +77,16 @@ uint32_t OatHeader::GetDexFileCount() const { return dex_file_count_; } +uint32_t OatHeader::GetElfImageCount() const { + DCHECK(IsValid()); + return elf_image_count_; +} + +uint32_t OatHeader::GetElfImageTableOffset() const { + DCHECK(IsValid()); + return elf_image_table_offset_; +} + uint32_t OatHeader::GetChecksum() const { CHECK(IsValid()); return adler32_checksum_; @@ -116,6 +131,12 @@ std::string OatHeader::GetImageFileLocation() const { GetImageFileLocationSize()); } +void OatHeader::SetElfImageTableOffset(uint32_t elf_image_table_offset) { + DCHECK(IsValid()); + elf_image_table_offset_ = elf_image_table_offset; + UpdateChecksum(&elf_image_table_offset_, sizeof(elf_image_table_offset_)); +} + void OatHeader::SetExecutableOffset(uint32_t executable_offset) { DCHECK_ALIGNED(executable_offset, kPageSize); CHECK_GT(executable_offset, sizeof(OatHeader)); @@ -30,6 +30,7 @@ class PACKED OatHeader { OatHeader(); OatHeader(InstructionSet instruction_set, const std::vector<const DexFile*>* dex_files, + uint32_t elf_image_count, uint32_t image_file_location_checksum, const std::string& image_file_location); @@ -38,8 +39,11 @@ class PACKED OatHeader { uint32_t GetChecksum() const; void UpdateChecksum(const void* data, size_t length); uint32_t GetDexFileCount() const; + uint32_t GetElfImageCount() const; + uint32_t GetElfImageTableOffset() const; uint32_t GetExecutableOffset() const; InstructionSet GetInstructionSet() const; + void SetElfImageTableOffset(uint32_t elf_image_offset); void SetExecutableOffset(uint32_t executable_offset); uint32_t GetImageFileLocationChecksum() const; uint32_t GetImageFileLocationSize() const; @@ -56,6 +60,8 @@ class PACKED OatHeader { InstructionSet instruction_set_; uint32_t dex_file_count_; + uint32_t elf_image_count_; + uint32_t elf_image_table_offset_; uint32_t executable_offset_; uint32_t image_file_location_checksum_; diff --git a/src/oat_writer.cc b/src/oat_writer.cc index 8e127de..df809d5 100644 --- a/src/oat_writer.cc +++ b/src/oat_writer.cc @@ -18,11 +18,14 @@ #include "class_linker.h" #include "class_loader.h" +#include "elf_image.h" #include "file.h" #include "os.h" #include "space.h" #include "stl_util.h" +#include <zlib.h> + namespace art { bool OatWriter::Create(File* file, @@ -49,12 +52,15 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, image_file_location_checksum_ = image_file_location_checksum; image_file_location_ = image_file_location; dex_files_ = &dex_files; + elf_images_ = compiler_->GetElfImages(); oat_header_ = NULL; executable_offset_padding_length_ = 0; size_t offset = InitOatHeader(); offset = InitOatDexFiles(offset); offset = InitDexFiles(offset); + offset = InitOatElfImages(offset); + offset = InitElfImages(offset); offset = InitOatClasses(offset); offset = InitOatCode(offset); offset = InitOatCodeDexFiles(offset); @@ -65,6 +71,7 @@ OatWriter::OatWriter(const std::vector<const DexFile*>& dex_files, OatWriter::~OatWriter() { delete oat_header_; STLDeleteElements(&oat_dex_files_); + STLDeleteElements(&oat_elf_images_); STLDeleteElements(&oat_classes_); } @@ -72,6 +79,7 @@ size_t OatWriter::InitOatHeader() { // create the OatHeader oat_header_ = new OatHeader(compiler_->GetInstructionSet(), dex_files_, + elf_images_.size(), image_file_location_checksum_, image_file_location_); size_t offset = sizeof(*oat_header_); @@ -106,6 +114,29 @@ size_t OatWriter::InitDexFiles(size_t offset) { return offset; } +size_t OatWriter::InitOatElfImages(size_t offset) { + // Offset to ELF image table should be rounded up to 4-byte aligned, so that + // we can read the uint32_t directly. + offset = RoundUp(offset, 4); + oat_header_->SetElfImageTableOffset(offset); + + for (size_t i = 0, n = elf_images_.size(); i < n; ++i) { + OatElfImage* oat_elf_image = new OatElfImage(elf_images_[i]); + oat_elf_images_.push_back(oat_elf_image); + offset += oat_elf_image->SizeOf(); + } + return offset; +} + +size_t OatWriter::InitElfImages(size_t offset) { + for (size_t i = 0; i < oat_elf_images_.size(); ++i) { + offset = RoundUp(offset, 4); + oat_elf_images_[i]->SetElfOffset(offset); + offset += oat_elf_images_[i]->GetElfSize(); + } + return offset; +} + size_t OatWriter::InitOatClasses(size_t offset) { // create the OatClasses // calculate the offsets within OatDexFiles to OatClasses @@ -424,6 +455,25 @@ bool OatWriter::WriteTables(File* file) { return false; } } + for (size_t i = 0; i != oat_elf_images_.size(); ++i) { + if (!oat_elf_images_[i]->Write(file)) { + PLOG(ERROR) << "Failed to write oat elf information to " << file->name(); + return false; + } + } + for (size_t i = 0; i != oat_elf_images_.size(); ++i) { + uint32_t expected_offset = oat_elf_images_[i]->GetElfOffset(); + off_t actual_offset = lseek(file->Fd(), expected_offset, SEEK_SET); + if (static_cast<uint32_t>(actual_offset) != expected_offset) { + PLOG(ERROR) << "Failed to seek to dex file section." + << " Actual: " << actual_offset + << " Expected: " << expected_offset; + return false; + } + if (!oat_elf_images_[i]->WriteElfImage(file)) { + return false; + } + } for (size_t i = 0; i != oat_classes_.size(); ++i) { if (!oat_classes_[i]->Write(file)) { PLOG(ERROR) << "Failed to write oat methods information to " << file->name(); @@ -772,4 +822,48 @@ bool OatWriter::OatClass::Write(File* file) const { return true; } +OatWriter::OatElfImage::OatElfImage(const ElfImage& image) + : elf_offset_(0), elf_size_(image.size()), elf_addr_(image.begin()) { +} + +size_t OatWriter::OatElfImage::SizeOf() const { + return (sizeof(elf_offset_) + sizeof(elf_size_)); +} + +uint32_t OatWriter::OatElfImage::GetElfSize() const { + return elf_size_; +} + +uint32_t OatWriter::OatElfImage::GetElfOffset() const { + DCHECK_NE(elf_offset_, 0U); + return elf_offset_; +} + +void OatWriter::OatElfImage::SetElfOffset(uint32_t offset) { + DCHECK_NE(offset, 0U); + DCHECK((offset & 0x3LU) == 0); + elf_offset_ = offset; +} + +bool OatWriter::OatElfImage::Write(File* file) const { + DCHECK_NE(elf_offset_, 0U); + if (!file->WriteFully(&elf_offset_, sizeof(elf_offset_))) { + PLOG(ERROR) << "Failed to write ELF offset to " << file->name(); + return false; + } + if (!file->WriteFully(&elf_size_, sizeof(elf_size_))) { + PLOG(ERROR) << "Failed to write ELF size to " << file->name(); + return false; + } + return true; +} + +bool OatWriter::OatElfImage::WriteElfImage(File* file) const { + if (!file->WriteFully(elf_addr_, elf_size_)) { + PLOG(ERROR) << "Failed to write ELF image to " << file->name(); + return false; + } + return true; +} + } // namespace art diff --git a/src/oat_writer.h b/src/oat_writer.h index c3a8ff6..e0d257f 100644 --- a/src/oat_writer.h +++ b/src/oat_writer.h @@ -48,6 +48,16 @@ namespace art { // ... // OatClass[C] // +// OatElfImage[0] one OatElfImage for each ELF image +// OatElfImage[1] contains the size, checksum, and offset to the ELF image. +// ... +// OatElfImage[E] +// +// ELF[0] +// ELF[1] +// ... +// ELF[E] +// // padding if necessary so that the following code will be page aligned // // CompiledMethod one variable sized blob with the contents of each CompiledMethod @@ -82,6 +92,8 @@ class OatWriter { size_t InitOatDexFiles(size_t offset); size_t InitDexFiles(size_t offset); size_t InitOatClasses(size_t offset); + size_t InitOatElfImages(size_t offset); + size_t InitElfImages(size_t offset); size_t InitOatCode(size_t offset); size_t InitOatCodeDexFiles(size_t offset); size_t InitOatCodeDexFile(size_t offset, @@ -143,6 +155,25 @@ class OatWriter { DISALLOW_COPY_AND_ASSIGN(OatClass); }; + class OatElfImage { + public: + explicit OatElfImage(const ElfImage& elf_image); + size_t SizeOf() const; + uint32_t GetElfSize() const; + uint32_t GetElfOffset() const; + void SetElfOffset(uint32_t offset); + bool Write(File* file) const; + bool WriteElfImage(File* file) const; + + private: + // data to write + uint32_t elf_offset_; + const uint32_t elf_size_; + + const byte* const elf_addr_; + DISALLOW_COPY_AND_ASSIGN(OatElfImage); + }; + const Compiler* compiler_; // TODO: remove the ClassLoader when the code storage moves out of Method @@ -151,6 +182,8 @@ class OatWriter { // note OatFile does not take ownership of the DexFiles const std::vector<const DexFile*>* dex_files_; + std::vector<ElfImage> elf_images_; + // dependency on the image uint32_t image_file_location_checksum_; std::string image_file_location_; @@ -159,6 +192,7 @@ class OatWriter { OatHeader* oat_header_; std::vector<OatDexFile*> oat_dex_files_; std::vector<OatClass*> oat_classes_; + std::vector<OatElfImage*> oat_elf_images_; uint32_t executable_offset_padding_length_; template <class T> struct MapCompare { |