diff options
Diffstat (limited to 'runtime/oat_file.cc')
| -rw-r--r-- | runtime/oat_file.cc | 147 |
1 files changed, 64 insertions, 83 deletions
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc index b0e1de2b81a..c7a558cc94f 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -40,6 +40,7 @@ #include "base/enums.h" #include "base/file_utils.h" #include "base/logging.h" // For VLOG_IS_ON. +#include "base/mem_map.h" #include "base/os.h" #include "base/stl_util.h" #include "base/systrace.h" @@ -49,19 +50,18 @@ #include "dex/dex_file_loader.h" #include "dex/dex_file_types.h" #include "dex/standard_dex_file.h" +#include "dex/type_lookup_table.h" #include "dex/utf-inl.h" #include "elf_file.h" #include "elf_utils.h" #include "gc_root.h" #include "gc/space/image_space.h" -#include "mem_map.h" #include "mirror/class.h" #include "mirror/object-inl.h" #include "oat.h" #include "oat_file-inl.h" #include "oat_file_manager.h" #include "runtime.h" -#include "type_lookup_table.h" #include "vdex_file.h" namespace art { @@ -343,6 +343,19 @@ bool OatFileBase::ComputeFields(uint8_t* requested_base, // Readjust to be non-inclusive upper bound. end_ += sizeof(uint32_t); + data_bimg_rel_ro_begin_ = FindDynamicSymbolAddress("oatdatabimgrelro", &symbol_error_msg); + if (data_bimg_rel_ro_begin_ != nullptr) { + data_bimg_rel_ro_end_ = + FindDynamicSymbolAddress("oatdatabimgrelrolastword", &symbol_error_msg); + if (data_bimg_rel_ro_end_ == nullptr) { + *error_msg = + StringPrintf("Failed to find oatdatabimgrelrolastword symbol in '%s'", file_path.c_str()); + return false; + } + // Readjust to be non-inclusive upper bound. + data_bimg_rel_ro_end_ += sizeof(uint32_t); + } + bss_begin_ = const_cast<uint8_t*>(FindDynamicSymbolAddress("oatbss", &symbol_error_msg)); if (bss_begin_ == nullptr) { // No .bss section. @@ -399,37 +412,6 @@ inline static bool ReadOatDexFileData(const OatFile& oat_file, return true; } -static inline bool MapConstantTables(const gc::space::ImageSpace* space, - uint8_t* address) { - // If MREMAP_DUP is ever merged to Linux kernel, use it to avoid the unnecessary open()/close(). - // Note: The current approach relies on the filename still referencing the same inode. - - File file(space->GetImageFilename(), O_RDONLY, /* checkUsage */ false); - if (!file.IsOpened()) { - LOG(ERROR) << "Failed to open boot image file " << space->GetImageFilename(); - return false; - } - - uint32_t offset = space->GetImageHeader().GetBootImageConstantTablesOffset(); - uint32_t size = space->GetImageHeader().GetBootImageConstantTablesSize(); - std::string error_msg; - std::unique_ptr<MemMap> mem_map(MemMap::MapFileAtAddress(address, - size, - PROT_READ, - MAP_PRIVATE, - file.Fd(), - offset, - /* low_4gb */ false, - /* reuse */ true, - file.GetPath().c_str(), - &error_msg)); - if (mem_map == nullptr) { - LOG(ERROR) << "Failed to mmap boot image tables from file " << space->GetImageFilename(); - return false; - } - return true; -} - static bool ReadIndexBssMapping(OatFile* oat_file, /*inout*/const uint8_t** oat, size_t dex_file_index, @@ -536,6 +518,17 @@ bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) { } const uint8_t* oat = Begin() + oat_dex_files_offset; // Jump to the OatDexFile records. + if (!IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_begin_) || + !IsAligned<sizeof(uint32_t)>(data_bimg_rel_ro_end_) || + data_bimg_rel_ro_begin_ > data_bimg_rel_ro_end_) { + *error_msg = StringPrintf("In oat file '%s' found unaligned or unordered databimgrelro " + "symbol(s): begin = %p, end = %p", + GetLocation().c_str(), + data_bimg_rel_ro_begin_, + data_bimg_rel_ro_end_); + return false; + } + DCHECK_GE(static_cast<size_t>(pointer_size), alignof(GcRoot<mirror::Object>)); if (!IsAligned<kPageSize>(bss_begin_) || !IsAlignedParam(bss_methods_, static_cast<size_t>(pointer_size)) || @@ -564,12 +557,15 @@ bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) { return false; } - uint8_t* after_tables = - (bss_methods_ != nullptr) ? bss_methods_ : bss_roots_; // May be null. - uint8_t* boot_image_tables = (bss_begin_ == after_tables) ? nullptr : bss_begin_; - uint8_t* boot_image_tables_end = - (bss_begin_ == after_tables) ? nullptr : (after_tables != nullptr) ? after_tables : bss_end_; - DCHECK_EQ(boot_image_tables != nullptr, boot_image_tables_end != nullptr); + if (bss_methods_ != nullptr && bss_methods_ != bss_begin_) { + *error_msg = StringPrintf("In oat file '%s' found unexpected .bss gap before 'oatbssmethods': " + "begin = %p, methods = %p", + GetLocation().c_str(), + bss_begin_, + bss_methods_); + return false; + } + uint32_t dex_file_count = GetOatHeader().GetDexFileCount(); oat_dex_files_storage_.reserve(dex_file_count); for (size_t i = 0; i < dex_file_count; i++) { @@ -849,39 +845,28 @@ bool OatFileBase::Setup(const char* abs_dex_location, std::string* error_msg) { } } - if (boot_image_tables != nullptr) { - Runtime* runtime = Runtime::Current(); + Runtime* runtime = Runtime::Current(); + + if (DataBimgRelRoBegin() != nullptr) { + // Make .data.bimg.rel.ro read only. ClassLinker shall make it writable for relocation. + uint8_t* reloc_begin = const_cast<uint8_t*>(DataBimgRelRoBegin()); + CheckedCall(mprotect, "protect relocations", reloc_begin, DataBimgRelRoSize(), PROT_READ); if (UNLIKELY(runtime == nullptr)) { - // This must be oatdump without boot image. Make sure the .bss is inaccessible. - CheckedCall(mprotect, "protect bss", const_cast<uint8_t*>(BssBegin()), BssSize(), PROT_NONE); + // This must be oatdump without boot image. } else if (!IsExecutable()) { - // Do not try to mmap boot image tables into .bss if the oat file is not executable. + // Do not check whether we have a boot image if the oat file is not executable. + } else if (UNLIKELY(runtime->GetHeap()->GetBootImageSpaces().empty())) { + *error_msg = StringPrintf("Cannot load oat file '%s' with .data.bimg.rel.ro as executable " + "without boot image.", + GetLocation().c_str()); + return false; } else { - // Map boot image tables into the .bss. The reserved size must match size of the tables. - size_t reserved_size = static_cast<size_t>(boot_image_tables_end - boot_image_tables); - size_t tables_size = 0u; - for (gc::space::ImageSpace* space : runtime->GetHeap()->GetBootImageSpaces()) { - tables_size += space->GetImageHeader().GetBootImageConstantTablesSize(); - DCHECK_ALIGNED(tables_size, kPageSize); - } - if (tables_size != reserved_size) { - *error_msg = StringPrintf("In oat file '%s' found unexpected boot image table sizes, " - " %zu bytes, should be %zu.", - GetLocation().c_str(), - reserved_size, - tables_size); - return false; - } - for (gc::space::ImageSpace* space : Runtime::Current()->GetHeap()->GetBootImageSpaces()) { - uint32_t current_tables_size = space->GetImageHeader().GetBootImageConstantTablesSize(); - if (current_tables_size != 0u && !MapConstantTables(space, boot_image_tables)) { - return false; - } - boot_image_tables += current_tables_size; - } - DCHECK(boot_image_tables == boot_image_tables_end); + // ClassLinker shall perform the relocation when we register a dex file from + // this oat file. We do not do the relocation here to avoid dirtying the pages + // if the code is never actually ready to be executed. } } + return true; } @@ -1513,6 +1498,8 @@ OatFile::OatFile(const std::string& location, bool is_executable) vdex_(nullptr), begin_(nullptr), end_(nullptr), + data_bimg_rel_ro_begin_(nullptr), + data_bimg_rel_ro_end_(nullptr), bss_begin_(nullptr), bss_end_(nullptr), bss_methods_(nullptr), @@ -1542,22 +1529,6 @@ const uint8_t* OatFile::End() const { return end_; } -const uint8_t* OatFile::BssBegin() const { - return bss_begin_; -} - -const uint8_t* OatFile::BssEnd() const { - return bss_end_; -} - -const uint8_t* OatFile::VdexBegin() const { - return vdex_begin_; -} - -const uint8_t* OatFile::VdexEnd() const { - return vdex_end_; -} - const uint8_t* OatFile::DexBegin() const { return vdex_->Begin(); } @@ -1566,6 +1537,16 @@ const uint8_t* OatFile::DexEnd() const { return vdex_->End(); } +ArrayRef<const uint32_t> OatFile::GetBootImageRelocations() const { + if (data_bimg_rel_ro_begin_ != nullptr) { + const uint32_t* relocations = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_begin_); + const uint32_t* relocations_end = reinterpret_cast<const uint32_t*>(data_bimg_rel_ro_end_); + return ArrayRef<const uint32_t>(relocations, relocations_end - relocations); + } else { + return ArrayRef<const uint32_t>(); + } +} + ArrayRef<ArtMethod*> OatFile::GetBssMethods() const { if (bss_methods_ != nullptr) { ArtMethod** methods = reinterpret_cast<ArtMethod**>(bss_methods_); |
