diff options
-rw-r--r-- | dex2oat/Android.bp | 4 | ||||
-rw-r--r-- | dex2oat/dex2oat.cc | 6 | ||||
-rw-r--r-- | dex2oat/dex2oat_test.cc | 4 | ||||
-rw-r--r-- | dex2oat/dex2oat_vdex_test.cc | 1 | ||||
-rw-r--r-- | dex2oat/linker/elf_writer_test.cc | 135 | ||||
-rw-r--r-- | runtime/oat/elf_file.cc | 655 | ||||
-rw-r--r-- | runtime/oat/elf_file.h | 28 | ||||
-rw-r--r-- | runtime/oat/elf_file_impl.h | 51 | ||||
-rw-r--r-- | runtime/oat/oat_file.cc | 116 | ||||
-rw-r--r-- | runtime/oat/oat_file_assistant.cc | 2 | ||||
-rw-r--r-- | runtime/oat/oat_file_manager.cc | 3 | ||||
-rw-r--r-- | runtime/runtime_test.cc | 2 | ||||
-rw-r--r-- | runtime/vdex_file.cc | 36 | ||||
-rw-r--r-- | runtime/vdex_file.h | 23 | ||||
-rw-r--r-- | runtime/vdex_file_test.cc | 4 |
15 files changed, 218 insertions, 852 deletions
diff --git a/dex2oat/Android.bp b/dex2oat/Android.bp index 186794e243..5df1fbbad2 100644 --- a/dex2oat/Android.bp +++ b/dex2oat/Android.bp @@ -410,6 +410,9 @@ art_cc_library_static { art_cc_defaults { name: "art_dex2oat_tests_defaults", + defaults: [ + "elfutils_transitive_defaults", // For libelf + ], device_common_data: [ ":art-gtest-jars-AbstractMethod", ":art-gtest-jars-ArrayClassWithUnresolvedComponent", @@ -506,6 +509,7 @@ art_cc_defaults { "liblog", ], static_libs: [ + "libelf", "libgmock", "liblz4", // libart(d)-dex2oat dependency; must be repeated here since it's a static lib. ], diff --git a/dex2oat/dex2oat.cc b/dex2oat/dex2oat.cc index a8d3d9346c..24bd112aef 100644 --- a/dex2oat/dex2oat.cc +++ b/dex2oat/dex2oat.cc @@ -1270,8 +1270,7 @@ class Dex2Oat final { if (!input_vdex_.empty()) { std::string error_msg; input_vdex_file_ = VdexFile::Open(input_vdex_, - /* writable */ false, - /* low_4gb */ false, + /*low_4gb=*/false, &error_msg); } @@ -1321,8 +1320,7 @@ class Dex2Oat final { input_vdex_file_ = VdexFile::Open(input_vdex_fd_, s.st_size, "vdex", - /* writable */ false, - /* low_4gb */ false, + /*low_4gb=*/false, &error_msg); // If there's any problem with the passed vdex, just warn and proceed // without it. diff --git a/dex2oat/dex2oat_test.cc b/dex2oat/dex2oat_test.cc index 9d837cbf67..97c467b600 100644 --- a/dex2oat/dex2oat_test.cc +++ b/dex2oat/dex2oat_test.cc @@ -1430,7 +1430,6 @@ TEST_F(Dex2oatTest, DontExtract) { { // Check the vdex doesn't have dex. std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location, - /*writable=*/false, /*low_4gb=*/false, &error_msg)); ASSERT_TRUE(vdex != nullptr); @@ -1776,7 +1775,6 @@ TEST_F(Dex2oatTest, DontCopyPlainDex) { // Check that the vdex doesn't have dex code. std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location, - /*writable=*/false, /*low_4gb=*/false, &error_msg)); ASSERT_TRUE(vdex != nullptr); @@ -2031,8 +2029,6 @@ TEST_F(Dex2oatTest, LoadOutOfDateOatFile) { { std::string error_msg; std::unique_ptr<ElfFile> elf_file(ElfFile::Open(file.get(), - /*writable=*/false, - /*program_header_only=*/true, /*low_4gb=*/false, &error_msg)); ASSERT_TRUE(elf_file != nullptr) << error_msg; diff --git a/dex2oat/dex2oat_vdex_test.cc b/dex2oat/dex2oat_vdex_test.cc index afea20cadf..4dc64e3289 100644 --- a/dex2oat/dex2oat_vdex_test.cc +++ b/dex2oat/dex2oat_vdex_test.cc @@ -74,7 +74,6 @@ class Dex2oatVdexTest : public Dex2oatEnvironmentTest { // Verify the vdex file content: only the classes using public APIs should be verified. std::string error_msg; std::unique_ptr<VdexFile> vdex(VdexFile::Open(vdex_location, - /*writable=*/false, /*low_4gb=*/false, &error_msg)); // Check the vdex doesn't have dex. diff --git a/dex2oat/linker/elf_writer_test.cc b/dex2oat/linker/elf_writer_test.cc index e37e41d3b5..913f865e8f 100644 --- a/dex2oat/linker/elf_writer_test.cc +++ b/dex2oat/linker/elf_writer_test.cc @@ -14,8 +14,13 @@ * limitations under the License. */ +#include <gelf.h> +#include <libelf.h> #include <sys/mman.h> // For the PROT_NONE constant. +#include <cstdint> + +#include "android-base/scopeguard.h" #include "base/file_utils.h" #include "base/mem_map.h" #include "base/unix_file/fd_file.h" @@ -83,18 +88,38 @@ class ElfWriterTest : public CommonCompilerDriverTest { } }; -#define EXPECT_ELF_FILE_ADDRESS(ef, expected_value, symbol_name, build_map) \ - do { \ - void* addr = reinterpret_cast<void*>((ef)->FindSymbolAddress(SHT_DYNSYM, \ - symbol_name, \ - build_map)); \ - EXPECT_NE(nullptr, addr); \ - if ((expected_value) == nullptr) { \ - (expected_value) = addr; \ - } \ - EXPECT_EQ(expected_value, addr); \ - EXPECT_EQ(expected_value, (ef)->FindDynamicSymbolAddress(symbol_name)); \ - } while (false) +static void FindSymbolAddress(File* file, const char* symbol_name, /*out*/ uint8_t** addr) { + ASSERT_NE(elf_version(EV_CURRENT), EV_NONE) << "libelf initialization failed: " << elf_errmsg(-1); + + Elf* elf = elf_begin(file->Fd(), ELF_C_READ, /*ref=*/nullptr); + ASSERT_NE(elf, nullptr) << elf_errmsg(-1); + auto elf_cleanup = android::base::make_scope_guard([&]() { elf_end(elf); }); + + Elf_Scn* dyn_scn = nullptr; + GElf_Shdr scn_hdr; + while ((dyn_scn = elf_nextscn(elf, dyn_scn)) != nullptr) { + ASSERT_EQ(gelf_getshdr(dyn_scn, &scn_hdr), &scn_hdr) << elf_errmsg(-1); + if (scn_hdr.sh_type == SHT_DYNSYM) { + break; + } + } + ASSERT_NE(dyn_scn, nullptr) << "Section SHT_DYNSYM not found"; + + Elf_Data* data = elf_getdata(dyn_scn, /*data=*/nullptr); + + // Iterate through dynamic section entries. + for (int i = 0; i < scn_hdr.sh_size / scn_hdr.sh_entsize; i++) { + GElf_Sym sym; + ASSERT_EQ(gelf_getsym(data, i, &sym), &sym) << elf_errmsg(-1); + const char* name = elf_strptr(elf, scn_hdr.sh_link, sym.st_name); + if (strcmp(name, symbol_name) == 0) { + *addr = reinterpret_cast<uint8_t*>(sym.st_value); + break; + } + } + + ASSERT_NE(*addr, nullptr) << "Symbol " << symbol_name << "not found"; +} TEST_F(ElfWriterTest, dlsym) { std::string elf_location = GetCoreOatLocation(); @@ -102,65 +127,65 @@ TEST_F(ElfWriterTest, dlsym) { LOG(INFO) << "elf_filename=" << elf_filename; UnreserveImageSpace(); - void* dl_oatdata = nullptr; - void* dl_oatexec = nullptr; - void* dl_oatlastword = nullptr; + uint8_t* dl_oatdata = nullptr; + uint8_t* dl_oatexec = nullptr; + uint8_t* dl_oatlastword = nullptr; std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str())); ASSERT_TRUE(file.get() != nullptr) << elf_filename; + ASSERT_NO_FATAL_FAILURE(FindSymbolAddress(file.get(), "oatdata", &dl_oatdata)); + ASSERT_NO_FATAL_FAILURE(FindSymbolAddress(file.get(), "oatexec", &dl_oatexec)); + ASSERT_NO_FATAL_FAILURE(FindSymbolAddress(file.get(), "oatlastword", &dl_oatlastword)); { std::string error_msg; std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), - /*writable=*/ false, - /*program_header_only=*/ false, /*low_4gb=*/false, &error_msg)); CHECK(ef.get() != nullptr) << error_msg; - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatdata, "oatdata", false); - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatexec, "oatexec", false); - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatlastword, "oatlastword", false); - } - { - std::string error_msg; - std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), - /*writable=*/ false, - /*program_header_only=*/ false, - /*low_4gb=*/ false, - &error_msg)); - CHECK(ef.get() != nullptr) << error_msg; - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatdata, "oatdata", true); - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatexec, "oatexec", true); - EXPECT_ELF_FILE_ADDRESS(ef, dl_oatlastword, "oatlastword", true); - } - { - std::string error_msg; - std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), - /*writable=*/ false, - /*program_header_only=*/ true, - /*low_4gb=*/ false, - &error_msg)); - CHECK(ef.get() != nullptr) << error_msg; size_t size; bool success = ef->GetLoadedSize(&size, &error_msg); CHECK(success) << error_msg; MemMap reservation = MemMap::MapAnonymous("ElfWriterTest#dlsym reservation", RoundUp(size, MemMap::GetPageSize()), PROT_NONE, - /*low_4gb=*/ true, + /*low_4gb=*/true, &error_msg); CHECK(reservation.IsValid()) << error_msg; uint8_t* base = reservation.Begin(); success = - ef->Load(file.get(), /*executable=*/ false, /*low_4gb=*/ false, &reservation, &error_msg); + ef->Load(file.get(), /*executable=*/false, /*low_4gb=*/false, &reservation, &error_msg); CHECK(success) << error_msg; CHECK(!reservation.IsValid()); EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatdata) + reinterpret_cast<uintptr_t>(base), - reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatdata"))); + reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatdata"))); EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatexec) + reinterpret_cast<uintptr_t>(base), - reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatexec"))); + reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatexec"))); EXPECT_EQ(reinterpret_cast<uintptr_t>(dl_oatlastword) + reinterpret_cast<uintptr_t>(base), - reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatlastword"))); + reinterpret_cast<uintptr_t>(ef->FindDynamicSymbolAddress("oatlastword"))); + } +} + +static void HasSection(File* file, const char* section_name, /*out*/ bool* result) { + ASSERT_NE(elf_version(EV_CURRENT), EV_NONE) << "libelf initialization failed: " << elf_errmsg(-1); + + Elf* elf = elf_begin(file->Fd(), ELF_C_READ, /*ref=*/nullptr); + ASSERT_NE(elf, nullptr) << elf_errmsg(-1); + auto elf_cleanup = android::base::make_scope_guard([&]() { elf_end(elf); }); + + size_t shstrndx = 0; + ASSERT_EQ(elf_getshdrstrndx(elf, &shstrndx), 0) << elf_errmsg(-1); + + Elf_Scn* dyn_scn = nullptr; + GElf_Shdr scn_hdr; + while ((dyn_scn = elf_nextscn(elf, dyn_scn)) != nullptr) { + ASSERT_EQ(gelf_getshdr(dyn_scn, &scn_hdr), &scn_hdr) << elf_errmsg(-1); + const char* name = elf_strptr(elf, shstrndx, scn_hdr.sh_name); + if (strcmp(name, section_name) == 0) { + *result = true; + return; + } } + *result = false; } TEST_F(ElfWriterTest, CheckBuildIdPresent) { @@ -170,16 +195,10 @@ TEST_F(ElfWriterTest, CheckBuildIdPresent) { std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str())); ASSERT_TRUE(file.get() != nullptr); - { - std::string error_msg; - std::unique_ptr<ElfFile> ef(ElfFile::Open(file.get(), - /*writable=*/ false, - /*program_header_only=*/ false, - /*low_4gb=*/ false, - &error_msg)); - CHECK(ef.get() != nullptr) << error_msg; - EXPECT_TRUE(ef->HasSection(".note.gnu.build-id")); - } + + bool result; + ASSERT_NO_FATAL_FAILURE(HasSection(file.get(), ".note.gnu.build-id", &result)); + EXPECT_TRUE(result); } // Check that dynamic sections (.dynamic, .dynsym, .dynstr, .hash) in an oat file are formed @@ -231,9 +250,7 @@ TEST_F(ElfWriterTest, CheckDynamicSection) { std::string error_msg; std::unique_ptr<ElfFile> ef(ElfFile::Open(tmp_oat.GetFile(), - /*writable=*/ false, - /*program_header_only=*/ true, - /*low_4gb=*/ false, + /*low_4gb=*/false, &error_msg)); ASSERT_NE(ef.get(), nullptr) << error_msg; ASSERT_TRUE(ef->Load(tmp_oat.GetFile(), diff --git a/runtime/oat/elf_file.cc b/runtime/oat/elf_file.cc index 76b8ed623c..8bbad65c94 100644 --- a/runtime/oat/elf_file.cc +++ b/runtime/oat/elf_file.cc @@ -21,14 +21,13 @@ #include <sys/types.h> #include <unistd.h> -#include "android-base/stringprintf.h" -#include "android-base/strings.h" +#include <memory> +#include "android-base/stringprintf.h" #include "arch/instruction_set.h" -#include "base/leb128.h" -#include "base/stl_util.h" +#include "base/casts.h" +#include "base/os.h" #include "base/unix_file/fd_file.h" -#include "base/utils.h" #include "elf/elf_utils.h" #include "elf_file_impl.h" @@ -37,43 +36,27 @@ namespace art HIDDEN { using android::base::StringPrintf; template <typename ElfTypes> -ElfFileImpl<ElfTypes>::ElfFileImpl(File* file, bool writable, bool program_header_only) - : writable_(writable), - program_header_only_(program_header_only), - header_(nullptr), - base_address_(nullptr), - program_headers_start_(nullptr), - section_headers_start_(nullptr), - dynamic_program_header_(nullptr), - dynamic_section_start_(nullptr), - symtab_section_start_(nullptr), - dynsym_section_start_(nullptr), - strtab_section_start_(nullptr), - dynstr_section_start_(nullptr), - hash_section_start_(nullptr), - symtab_symbol_table_(nullptr), - dynsym_symbol_table_(nullptr) { +ElfFileImpl<ElfTypes>::ElfFileImpl(File* file) + : header_(nullptr), + base_address_(nullptr), + program_headers_start_(nullptr), + section_headers_start_(nullptr), + dynamic_program_header_(nullptr), + dynamic_section_start_(nullptr), + symtab_section_start_(nullptr), + dynsym_section_start_(nullptr), + strtab_section_start_(nullptr), + dynstr_section_start_(nullptr), + hash_section_start_(nullptr) { CHECK(file != nullptr); } template <typename ElfTypes> ElfFileImpl<ElfTypes>* ElfFileImpl<ElfTypes>::Open(File* file, - bool writable, - bool program_header_only, bool low_4gb, std::string* error_msg) { - std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file( - new ElfFileImpl<ElfTypes>(file, writable, program_header_only)); - int prot; - int flags; - if (writable) { - prot = PROT_READ | PROT_WRITE; - flags = MAP_SHARED; - } else { - prot = PROT_READ; - flags = MAP_PRIVATE; - } - if (!elf_file->Setup(file, prot, flags, low_4gb, error_msg)) { + std::unique_ptr<ElfFileImpl<ElfTypes>> elf_file(new ElfFileImpl<ElfTypes>(file)); + if (!elf_file->Setup(file, PROT_READ, MAP_PRIVATE, low_4gb, error_msg)) { return nullptr; } return elf_file.release(); @@ -100,229 +83,51 @@ bool ElfFileImpl<ElfTypes>::Setup(File* file, return false; } - if (program_header_only_) { - // first just map ELF header to get program header size information - size_t elf_header_size = sizeof(Elf_Ehdr); - if (!SetMap(file, - MemMap::MapFile(elf_header_size, - prot, - flags, - file->Fd(), - 0, - low_4gb, - file->GetPath().c_str(), - error_msg), - error_msg)) { - return false; - } - // then remap to cover program header - size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum); - if (file_length < program_header_size) { - *error_msg = StringPrintf("File size of %zd bytes not large enough to contain ELF program " - "header of %zd bytes: '%s'", file_length, - sizeof(Elf_Ehdr), file->GetPath().c_str()); - return false; - } - if (!SetMap(file, - MemMap::MapFile(program_header_size, - prot, - flags, - file->Fd(), - 0, - low_4gb, - file->GetPath().c_str(), - error_msg), - error_msg)) { - *error_msg = StringPrintf("Failed to map ELF program headers: %s", error_msg->c_str()); - return false; - } - } else { - // otherwise map entire file - if (!SetMap(file, - MemMap::MapFile(file->GetLength(), - prot, - flags, - file->Fd(), - 0, - low_4gb, - file->GetPath().c_str(), - error_msg), - error_msg)) { - *error_msg = StringPrintf("Failed to map ELF file: %s", error_msg->c_str()); - return false; - } - } - - if (program_header_only_) { - program_headers_start_ = Begin() + GetHeader().e_phoff; - } else { - if (!CheckAndSet(GetHeader().e_phoff, "program headers", &program_headers_start_, error_msg)) { - return false; - } - - // Setup section headers. - if (!CheckAndSet(GetHeader().e_shoff, "section headers", §ion_headers_start_, error_msg)) { - return false; - } - - // Find shstrtab. - Elf_Shdr* shstrtab_section_header = GetSectionNameStringSection(); - if (shstrtab_section_header == nullptr) { - *error_msg = StringPrintf("Failed to find shstrtab section header in ELF file: '%s'", - file->GetPath().c_str()); - return false; - } - - // Find .dynamic section info from program header - dynamic_program_header_ = FindProgamHeaderByType(PT_DYNAMIC); - if (dynamic_program_header_ == nullptr) { - *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'", - file->GetPath().c_str()); - return false; - } - - if (!CheckAndSet(GetDynamicProgramHeader().p_offset, "dynamic section", - reinterpret_cast<uint8_t**>(&dynamic_section_start_), error_msg)) { - return false; - } - - // Find other sections from section headers - for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) { - Elf_Shdr* section_header = GetSectionHeader(i); - if (section_header == nullptr) { - *error_msg = StringPrintf("Failed to find section header for section %d in ELF file: '%s'", - i, file->GetPath().c_str()); - return false; - } - switch (section_header->sh_type) { - case SHT_SYMTAB: { - if (!CheckAndSet(section_header->sh_offset, "symtab", - reinterpret_cast<uint8_t**>(&symtab_section_start_), error_msg)) { - return false; - } - break; - } - case SHT_DYNSYM: { - if (!CheckAndSet(section_header->sh_offset, "dynsym", - reinterpret_cast<uint8_t**>(&dynsym_section_start_), error_msg)) { - return false; - } - break; - } - case SHT_STRTAB: { - // TODO: base these off of sh_link from .symtab and .dynsym above - if ((section_header->sh_flags & SHF_ALLOC) != 0) { - // Check that this is named ".dynstr" and ignore otherwise. - const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name); - if (strncmp(".dynstr", header_name, 8) == 0) { - if (!CheckAndSet(section_header->sh_offset, "dynstr", - reinterpret_cast<uint8_t**>(&dynstr_section_start_), error_msg)) { - return false; - } - } - } else { - // Check that this is named ".strtab" and ignore otherwise. - const char* header_name = GetString(*shstrtab_section_header, section_header->sh_name); - if (strncmp(".strtab", header_name, 8) == 0) { - if (!CheckAndSet(section_header->sh_offset, "strtab", - reinterpret_cast<uint8_t**>(&strtab_section_start_), error_msg)) { - return false; - } - } - } - break; - } - case SHT_DYNAMIC: { - if (reinterpret_cast<uint8_t*>(dynamic_section_start_) != - Begin() + section_header->sh_offset) { - LOG(WARNING) << "Failed to find matching SHT_DYNAMIC for PT_DYNAMIC in " - << file->GetPath() << ": " << std::hex - << reinterpret_cast<void*>(dynamic_section_start_) - << " != " << reinterpret_cast<void*>(Begin() + section_header->sh_offset); - return false; - } - break; - } - case SHT_HASH: { - if (!CheckAndSet(section_header->sh_offset, "hash section", - reinterpret_cast<uint8_t**>(&hash_section_start_), error_msg)) { - return false; - } - break; - } - } - } - - // Check for the existence of some sections. - if (!CheckSectionsExist(file, error_msg)) { - return false; - } + // first just map ELF header to get program header size information + size_t elf_header_size = sizeof(Elf_Ehdr); + if (!SetMap(file, + MemMap::MapFile(elf_header_size, + prot, + flags, + file->Fd(), + 0, + low_4gb, + file->GetPath().c_str(), + error_msg), + error_msg)) { + return false; } - - return true; -} - -template <typename ElfTypes> -ElfFileImpl<ElfTypes>::~ElfFileImpl() { - delete symtab_symbol_table_; - delete dynsym_symbol_table_; -} - -template <typename ElfTypes> -bool ElfFileImpl<ElfTypes>::CheckAndSet(Elf32_Off offset, const char* label, - uint8_t** target, std::string* error_msg) { - if (Begin() + offset >= End()) { - *error_msg = StringPrintf("Offset %d is out of range for %s in ELF file: '%s'", offset, label, - file_path_.c_str()); + // then remap to cover program header + size_t program_header_size = header_->e_phoff + (header_->e_phentsize * header_->e_phnum); + if (file_length < program_header_size) { + *error_msg = StringPrintf( + "File size of %zd bytes not large enough to contain ELF program header of %zd bytes: '%s'", + file_length, + sizeof(Elf_Ehdr), + file->GetPath().c_str()); return false; } - *target = Begin() + offset; - return true; -} - -template <typename ElfTypes> -bool ElfFileImpl<ElfTypes>::CheckSectionsLinked(const uint8_t* source, - const uint8_t* target) const { - // Only works in whole-program mode, as we need to iterate over the sections. - // Note that we normally can't search by type, as duplicates are allowed for most section types. - if (program_header_only_) { - return true; + if (!SetMap(file, + MemMap::MapFile(program_header_size, + prot, + flags, + file->Fd(), + 0, + low_4gb, + file->GetPath().c_str(), + error_msg), + error_msg)) { + *error_msg = StringPrintf("Failed to map ELF program headers: %s", error_msg->c_str()); + return false; } - Elf_Shdr* source_section = nullptr; - Elf_Word target_index = 0; - bool target_found = false; - for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) { - Elf_Shdr* section_header = GetSectionHeader(i); - - if (Begin() + section_header->sh_offset == source) { - // Found the source. - source_section = section_header; - if (target_index) { - break; - } - } else if (Begin() + section_header->sh_offset == target) { - target_index = i; - target_found = true; - if (source_section != nullptr) { - break; - } - } - } + program_headers_start_ = Begin() + GetHeader().e_phoff; - return target_found && source_section != nullptr && source_section->sh_link == target_index; + return true; } template <typename ElfTypes> - bool ElfFileImpl<ElfTypes>::CheckSectionsExist(File* file, std::string* error_msg) const { - if (!program_header_only_) { - // If in full mode, need section headers. - if (section_headers_start_ == nullptr) { - *error_msg = StringPrintf("No section headers in ELF file: '%s'", file->GetPath().c_str()); - return false; - } - } - +bool ElfFileImpl<ElfTypes>::CheckSectionsExist(File* file, std::string* error_msg) const { // This is redundant, but defensive. if (dynamic_program_header_ == nullptr) { *error_msg = StringPrintf("Failed to find PT_DYNAMIC program header in ELF file: '%s'", @@ -345,14 +150,6 @@ template <typename ElfTypes> *error_msg = StringPrintf("No strtab for symtab in ELF file: '%s'", file->GetPath().c_str()); return false; } - - // The symtab should link to the strtab. - if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(symtab_section_start_), - reinterpret_cast<const uint8_t*>(strtab_section_start_))) { - *error_msg = StringPrintf("Symtab is not linked to the strtab in ELF file: '%s'", - file->GetPath().c_str()); - return false; - } } // We always need a dynstr & dynsym. @@ -372,28 +169,17 @@ template <typename ElfTypes> return false; } - // And the hash section should be linking to the dynsym. - if (!CheckSectionsLinked(reinterpret_cast<const uint8_t*>(hash_section_start_), - reinterpret_cast<const uint8_t*>(dynsym_section_start_))) { - *error_msg = StringPrintf("Hash section is not linked to the dynstr in ELF file: '%s'", - file->GetPath().c_str()); + // We'd also like to confirm a shstrtab. This is usually the last in an oat file, and a good + // indicator of whether writing was successful (or the process crashed and left garbage). + // It might not be mapped, but we can compare against the file size. + int64_t offset = static_cast<int64_t>(GetHeader().e_shoff + + (GetHeader().e_shstrndx * GetHeader().e_shentsize)); + if (offset >= file->GetLength()) { + *error_msg = + StringPrintf("Shstrtab is not in the mapped ELF file: '%s'", file->GetPath().c_str()); return false; } - // We'd also like to confirm a shstrtab in program_header_only_ mode (else Open() does this for - // us). This is usually the last in an oat file, and a good indicator of whether writing was - // successful (or the process crashed and left garbage). - if (program_header_only_) { - // It might not be mapped, but we can compare against the file size. - int64_t offset = static_cast<int64_t>(GetHeader().e_shoff + - (GetHeader().e_shstrndx * GetHeader().e_shentsize)); - if (offset >= file->GetLength()) { - *error_msg = StringPrintf("Shstrtab is not in the mapped ELF file: '%s'", - file->GetPath().c_str()); - return false; - } - } - return true; } @@ -512,23 +298,6 @@ bool ElfFileImpl<ElfTypes>::SetMap(File* file, MemMap&& map, std::string* error_ file->GetPath().c_str()); return false; } - - if (!program_header_only_) { - if (header_->e_phoff >= Size()) { - *error_msg = StringPrintf("Failed to find e_phoff value %" PRIu64 " less than %zd in %s", - static_cast<uint64_t>(header_->e_phoff), - Size(), - file->GetPath().c_str()); - return false; - } - if (header_->e_shoff >= Size()) { - *error_msg = StringPrintf("Failed to find e_shoff value %" PRIu64 " less than %zd in %s", - static_cast<uint64_t>(header_->e_shoff), - Size(), - file->GetPath().c_str()); - return false; - } - } return true; } @@ -545,13 +314,6 @@ uint8_t* ElfFileImpl<ElfTypes>::GetProgramHeadersStart() const { } template <typename ElfTypes> -uint8_t* ElfFileImpl<ElfTypes>::GetSectionHeadersStart() const { - CHECK(!program_header_only_); // Only used in "full" mode. - CHECK(section_headers_start_ != nullptr); // Is checked in CheckSectionsExist - return section_headers_start_; -} - -template <typename ElfTypes> typename ElfTypes::Phdr& ElfFileImpl<ElfTypes>::GetDynamicProgramHeader() const { CHECK(dynamic_program_header_ != nullptr); // Is checked in CheckSectionsExist return *dynamic_program_header_; @@ -684,35 +446,6 @@ typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetSectionHeaderNum() const { return GetHeader().e_shnum; } -template <typename ElfTypes> -typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionHeader(Elf_Word i) const { - // Can only access arbitrary sections when we have the whole file, not just program header. - // Even if we Load(), it doesn't bring in all the sections. - CHECK(!program_header_only_) << file_path_; - if (i >= GetSectionHeaderNum()) { - return nullptr; // Failure condition. - } - uint8_t* section_header = GetSectionHeadersStart() + (i * GetHeader().e_shentsize); - if (section_header >= End()) { - return nullptr; // Failure condition. - } - return reinterpret_cast<Elf_Shdr*>(section_header); -} - -template <typename ElfTypes> -typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByType(Elf_Word type) const { - // Can only access arbitrary sections when we have the whole file, not just program header. - // We could change this to switch on known types if they were detected during loading. - CHECK(!program_header_only_) << file_path_; - for (Elf_Word i = 0; i < GetSectionHeaderNum(); i++) { - Elf_Shdr* section_header = GetSectionHeader(i); - if (section_header->sh_type == type) { - return section_header; - } - } - return nullptr; -} - // from bionic static unsigned elfhash(const char *_name) { const unsigned char *name = (const unsigned char *) _name; @@ -728,11 +461,6 @@ static unsigned elfhash(const char *_name) { } template <typename ElfTypes> -typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::GetSectionNameStringSection() const { - return GetSectionHeader(GetHeader().e_shstrndx); -} - -template <typename ElfTypes> const uint8_t* ElfFileImpl<ElfTypes>::FindDynamicSymbolAddress( const std::string& symbol_name) const { // Check that we have a hash section. @@ -804,137 +532,6 @@ typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::GetSymbol(Elf_Word section_type, } template <typename ElfTypes> -typename ElfFileImpl<ElfTypes>::SymbolTable** -ElfFileImpl<ElfTypes>::GetSymbolTable(Elf_Word section_type) { - CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; - switch (section_type) { - case SHT_SYMTAB: { - return &symtab_symbol_table_; - } - case SHT_DYNSYM: { - return &dynsym_symbol_table_; - } - default: { - LOG(FATAL) << section_type; - return nullptr; - } - } -} - -template <typename ElfTypes> -typename ElfTypes::Sym* ElfFileImpl<ElfTypes>::FindSymbolByName( - Elf_Word section_type, const std::string& symbol_name, bool build_map) { - CHECK(!program_header_only_) << file_path_; - CHECK(IsSymbolSectionType(section_type)) << file_path_ << " " << section_type; - - SymbolTable** symbol_table = GetSymbolTable(section_type); - if (*symbol_table != nullptr || build_map) { - if (*symbol_table == nullptr) { - DCHECK(build_map); - *symbol_table = new SymbolTable; - Elf_Shdr* symbol_section = FindSectionByType(section_type); - if (symbol_section == nullptr) { - return nullptr; // Failure condition. - } - Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link); - if (string_section == nullptr) { - return nullptr; // Failure condition. - } - for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) { - Elf_Sym* symbol = GetSymbol(section_type, i); - if (symbol == nullptr) { - return nullptr; // Failure condition. - } - unsigned char type = (sizeof(Elf_Addr) == sizeof(Elf64_Addr)) - ? ELF64_ST_TYPE(symbol->st_info) - : ELF32_ST_TYPE(symbol->st_info); - if (type == STT_NOTYPE) { - continue; - } - const char* name = GetString(*string_section, symbol->st_name); - if (name == nullptr) { - continue; - } - std::pair<typename SymbolTable::iterator, bool> result = - (*symbol_table)->insert(std::make_pair(name, symbol)); - if (!result.second) { - // If a duplicate, make sure it has the same logical value. Seen on x86. - if ((symbol->st_value != result.first->second->st_value) || - (symbol->st_size != result.first->second->st_size) || - (symbol->st_info != result.first->second->st_info) || - (symbol->st_other != result.first->second->st_other) || - (symbol->st_shndx != result.first->second->st_shndx)) { - return nullptr; // Failure condition. - } - } - } - } - CHECK(*symbol_table != nullptr); - typename SymbolTable::const_iterator it = (*symbol_table)->find(symbol_name); - if (it == (*symbol_table)->end()) { - return nullptr; - } - return it->second; - } - - // Fall back to linear search - Elf_Shdr* symbol_section = FindSectionByType(section_type); - if (symbol_section == nullptr) { - return nullptr; - } - Elf_Shdr* string_section = GetSectionHeader(symbol_section->sh_link); - if (string_section == nullptr) { - return nullptr; - } - for (uint32_t i = 0; i < GetSymbolNum(*symbol_section); i++) { - Elf_Sym* symbol = GetSymbol(section_type, i); - if (symbol == nullptr) { - return nullptr; // Failure condition. - } - const char* name = GetString(*string_section, symbol->st_name); - if (name == nullptr) { - continue; - } - if (symbol_name == name) { - return symbol; - } - } - return nullptr; -} - -template <typename ElfTypes> -typename ElfTypes::Addr ElfFileImpl<ElfTypes>::FindSymbolAddress( - Elf_Word section_type, const std::string& symbol_name, bool build_map) { - Elf_Sym* symbol = FindSymbolByName(section_type, symbol_name, build_map); - if (symbol == nullptr) { - return 0; - } - return symbol->st_value; -} - -template <typename ElfTypes> -const char* ElfFileImpl<ElfTypes>::GetString(Elf_Shdr& string_section, - Elf_Word i) const { - CHECK(!program_header_only_) << file_path_; - // TODO: remove this static_cast from enum when using -std=gnu++0x - if (static_cast<Elf_Word>(SHT_STRTAB) != string_section.sh_type) { - return nullptr; // Failure condition. - } - if (i >= string_section.sh_size) { - return nullptr; - } - if (i == 0) { - return nullptr; - } - uint8_t* strings = Begin() + string_section.sh_offset; - uint8_t* string = strings + i; - if (string >= End()) { - return nullptr; - } - return reinterpret_cast<const char*>(string); -} - -template <typename ElfTypes> typename ElfTypes::Word ElfFileImpl<ElfTypes>::GetDynamicNum() const { return GetDynamicProgramHeader().p_filesz / sizeof(Elf_Dyn); } @@ -1036,10 +633,8 @@ template <typename ElfTypes> bool ElfFileImpl<ElfTypes>::Load(File* file, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, - /*out*/std::string* error_msg) { - CHECK(program_header_only_) << file->GetPath(); - + /*inout*/ MemMap* reservation, + /*out*/ std::string* error_msg) { if (executable) { InstructionSet elf_ISA = GetInstructionSetFromELF(GetHeader().e_machine, GetHeader().e_flags); if (elf_ISA != kRuntimeQuickCodeISA) { @@ -1132,13 +727,6 @@ bool ElfFileImpl<ElfTypes>::Load(File* file, if ((program_header->p_flags & PF_R) != 0) { prot |= PROT_READ; } - int flags = 0; - if (writable_) { - prot |= PROT_WRITE; - flags |= MAP_SHARED; - } else { - flags |= MAP_PRIVATE; - } if (program_header->p_filesz > program_header->p_memsz) { *error_msg = StringPrintf("Invalid p_filesz > p_memsz (%" PRIu64 " > %" PRIu64 "): %s", static_cast<uint64_t>(program_header->p_filesz), @@ -1163,18 +751,17 @@ bool ElfFileImpl<ElfTypes>::Load(File* file, return false; } if (program_header->p_filesz != 0u) { - MemMap segment = - MemMap::MapFileAtAddress(p_vaddr, - program_header->p_filesz, - prot, - flags, - file->Fd(), - program_header->p_offset, - /* low_4gb= */ false, - file->GetPath().c_str(), - /* reuse= */ true, // implies MAP_FIXED - /* reservation= */ nullptr, - error_msg); + MemMap segment = MemMap::MapFileAtAddress(p_vaddr, + program_header->p_filesz, + prot, + MAP_PRIVATE, + file->Fd(), + program_header->p_offset, + /*low_4gb=*/false, + file->GetPath().c_str(), + /*reuse=*/true, // implies MAP_FIXED + /*reservation=*/nullptr, + error_msg); if (!segment.IsValid()) { *error_msg = StringPrintf("Failed to map ELF file segment %d from %s: %s", i, file->GetPath().c_str(), error_msg->c_str()); @@ -1195,9 +782,9 @@ bool ElfFileImpl<ElfTypes>::Load(File* file, p_vaddr + program_header->p_filesz, program_header->p_memsz - program_header->p_filesz, prot, - /* low_4gb= */ false, - /* reuse= */ true, - /* reservation= */ nullptr, + /*low_4gb=*/false, + /*reuse=*/true, + /*reservation=*/nullptr, error_msg); if (!segment.IsValid()) { *error_msg = StringPrintf("Failed to map zero-initialized ELF file segment %d from %s: %s", @@ -1284,31 +871,6 @@ bool ElfFileImpl<ElfTypes>::ValidPointer(const uint8_t* start) const { return false; } - -template <typename ElfTypes> -typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByName( - const std::string& name) const { - CHECK(!program_header_only_); - Elf_Shdr* shstrtab_sec = GetSectionNameStringSection(); - if (shstrtab_sec == nullptr) { - return nullptr; - } - for (uint32_t i = 0; i < GetSectionHeaderNum(); i++) { - Elf_Shdr* shdr = GetSectionHeader(i); - if (shdr == nullptr) { - return nullptr; - } - const char* sec_name = GetString(*shstrtab_sec, shdr->sh_name); - if (sec_name == nullptr) { - continue; - } - if (name == sec_name) { - return shdr; - } - } - return nullptr; -} - // Explicit instantiations template class ElfFileImpl<ElfTypes32>; template class ElfFileImpl<ElfTypes64>; @@ -1325,10 +887,8 @@ ElfFile::~ElfFile() { } ElfFile* ElfFile::Open(File* file, - bool writable, - bool program_header_only, bool low_4gb, - /*out*/std::string* error_msg) { + /*out*/ std::string* error_msg) { if (file->GetLength() < EI_NIDENT) { *error_msg = StringPrintf("File %s is too short to be a valid ELF file", file->GetPath().c_str()); @@ -1347,21 +907,13 @@ ElfFile* ElfFile::Open(File* file, } uint8_t* header = map.Begin(); if (header[EI_CLASS] == ELFCLASS64) { - ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, - writable, - program_header_only, - low_4gb, - error_msg); + ElfFileImpl64* elf_file_impl = ElfFileImpl64::Open(file, low_4gb, error_msg); if (elf_file_impl == nullptr) { return nullptr; } return new ElfFile(elf_file_impl); } else if (header[EI_CLASS] == ELFCLASS32) { - ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, - writable, - program_header_only, - low_4gb, - error_msg); + ElfFileImpl32* elf_file_impl = ElfFileImpl32::Open(file, low_4gb, error_msg); if (elf_file_impl == nullptr) { return nullptr; } @@ -1411,51 +963,6 @@ const std::string& ElfFile::GetFilePath() const { DELEGATE_TO_IMPL(GetFilePath); } -bool ElfFile::GetSectionOffsetAndSize(const char* section_name, uint64_t* offset, - uint64_t* size) const { - if (elf32_.get() == nullptr) { - CHECK(elf64_.get() != nullptr); - - Elf64_Shdr *shdr = elf64_->FindSectionByName(section_name); - if (shdr == nullptr) { - return false; - } - if (offset != nullptr) { - *offset = shdr->sh_offset; - } - if (size != nullptr) { - *size = shdr->sh_size; - } - return true; - } else { - Elf32_Shdr *shdr = elf32_->FindSectionByName(section_name); - if (shdr == nullptr) { - return false; - } - if (offset != nullptr) { - *offset = shdr->sh_offset; - } - if (size != nullptr) { - *size = shdr->sh_size; - } - return true; - } -} - -bool ElfFile::HasSection(const std::string& name) const { - if (elf64_.get() != nullptr) { - return elf64_->FindSectionByName(name) != nullptr; - } else { - return elf32_->FindSectionByName(name) != nullptr; - } -} - -uint64_t ElfFile::FindSymbolAddress(unsigned section_type, - const std::string& symbol_name, - bool build_map) { - DELEGATE_TO_IMPL(FindSymbolAddress, section_type, symbol_name, build_map); -} - bool ElfFile::GetLoadedSize(size_t* size, std::string* error_msg) const { DELEGATE_TO_IMPL(GetLoadedSize, size, error_msg); } diff --git a/runtime/oat/elf_file.h b/runtime/oat/elf_file.h index ccfe82e0c2..4206e1926a 100644 --- a/runtime/oat/elf_file.h +++ b/runtime/oat/elf_file.h @@ -41,10 +41,8 @@ using ElfFileImpl64 = ElfFileImpl<ElfTypes64>; class ElfFile { public: static ElfFile* Open(File* file, - bool writable, - bool program_header_only, bool low_4gb, - /*out*/std::string* error_msg); + /*out*/ std::string* error_msg); ~ElfFile(); @@ -52,8 +50,8 @@ class ElfFile { bool Load(File* file, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, - /*out*/std::string* error_msg); + /*inout*/ MemMap* reservation, + /*out*/ std::string* error_msg); const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name) const; @@ -67,31 +65,17 @@ class ElfFile { const std::string& GetFilePath() const; - bool GetSectionOffsetAndSize(const char* section_name, uint64_t* offset, uint64_t* size) const; - - bool HasSection(const std::string& name) const; - - uint64_t FindSymbolAddress(unsigned section_type, - const std::string& symbol_name, - bool build_map); - bool GetLoadedSize(size_t* size, std::string* error_msg) const; size_t GetElfSegmentAlignmentFromFile() const; const uint8_t* GetBaseAddress() const; - bool Is64Bit() const { - return elf64_.get() != nullptr; - } + bool Is64Bit() const { return elf64_.get() != nullptr; } - ElfFileImpl32* GetImpl32() const { - return elf32_.get(); - } + ElfFileImpl32* GetImpl32() const { return elf32_.get(); } - ElfFileImpl64* GetImpl64() const { - return elf64_.get(); - } + ElfFileImpl64* GetImpl64() const { return elf64_.get(); } private: explicit ElfFile(ElfFileImpl32* elf32); diff --git a/runtime/oat/elf_file_impl.h b/runtime/oat/elf_file_impl.h index 67e9558cd2..0e8dc6ac89 100644 --- a/runtime/oat/elf_file_impl.h +++ b/runtime/oat/elf_file_impl.h @@ -17,14 +17,11 @@ #ifndef ART_RUNTIME_OAT_ELF_FILE_IMPL_H_ #define ART_RUNTIME_OAT_ELF_FILE_IMPL_H_ -#include <map> -#include <memory> -#include <type_traits> #include <vector> #include "base/macros.h" #include "base/mem_map.h" -#include "elf/elf_utils.h" +#include "base/os.h" namespace art HIDDEN { @@ -45,13 +42,9 @@ class ElfFileImpl { using Elf_Dyn = typename ElfTypes::Dyn; static ElfFileImpl* Open(File* file, - bool writable, - bool program_header_only, bool low_4gb, /*out*/ std::string* error_msg); - ~ElfFileImpl(); - const std::string& GetFilePath() const { return file_path_; } @@ -78,11 +71,7 @@ class ElfFileImpl { Elf_Phdr* GetProgramHeader(Elf_Word) const; Elf_Word GetSectionHeaderNum() const; - Elf_Shdr* GetSectionHeader(Elf_Word) const; Elf_Shdr* FindSectionByType(Elf_Word type) const; - Elf_Shdr* FindSectionByName(const std::string& name) const; - - Elf_Shdr* GetSectionNameStringSection() const; // Find .dynsym using .hash for more efficient lookup than FindSymbolAddress. const uint8_t* FindDynamicSymbolAddress(const std::string& symbol_name) const; @@ -91,15 +80,6 @@ class ElfFileImpl { Elf_Word GetSymbolNum(Elf_Shdr&) const; Elf_Sym* GetSymbol(Elf_Word section_type, Elf_Word i) const; - // Find address of symbol in specified table, returning 0 if it is - // not found. See FindSymbolByName for an explanation of build_map. - Elf_Addr FindSymbolAddress(Elf_Word section_type, - const std::string& symbol_name, - bool build_map); - - // Lookup a string given string section and offset. Returns null for special 0 offset. - const char* GetString(Elf_Shdr&, Elf_Word) const; - Elf_Word GetDynamicNum() const; Elf_Dyn& GetDynamic(Elf_Word) const; @@ -118,7 +98,7 @@ class ElfFileImpl { /*out*/std::string* error_msg); private: - ElfFileImpl(File* file, bool writable, bool program_header_only); + explicit ElfFileImpl(File* file); bool GetLoadedAddressRange(/*out*/uint8_t** vaddr_begin, /*out*/size_t* vaddr_size, @@ -129,7 +109,6 @@ class ElfFileImpl { bool SetMap(File* file, MemMap&& map, std::string* error_msg); uint8_t* GetProgramHeadersStart() const; - uint8_t* GetSectionHeadersStart() const; Elf_Phdr& GetDynamicProgramHeader() const; Elf_Dyn* GetDynamicSectionStart() const; Elf_Sym* GetSymbolSectionStart(Elf_Word section_type) const; @@ -140,9 +119,6 @@ class ElfFileImpl { Elf_Word GetHashBucket(size_t i, bool* ok) const; Elf_Word GetHashChain(size_t i, bool* ok) const; - using SymbolTable = std::map<std::string, Elf_Sym*>; - SymbolTable** GetSymbolTable(Elf_Word section_type); - bool ValidPointer(const uint8_t* start) const; const Elf_Sym* FindDynamicSymbol(const std::string& symbol_name) const; @@ -150,32 +126,12 @@ class ElfFileImpl { // Check that certain sections and their dependencies exist. bool CheckSectionsExist(File* file, std::string* error_msg) const; - // Check that the link of the first section links to the second section. - bool CheckSectionsLinked(const uint8_t* source, const uint8_t* target) const; - - // Check whether the offset is in range, and set to target to Begin() + offset if OK. - bool CheckAndSet(Elf32_Off offset, const char* label, uint8_t** target, std::string* error_msg); - - // Find symbol in specified table, returning null if it is not found. - // - // If build_map is true, builds a map to speed repeated access. The - // map does not included untyped symbol values (aka STT_NOTYPE) - // since they can contain duplicates. If build_map is false, the map - // will be used if it was already created. Typically build_map - // should be set unless only a small number of symbols will be - // looked up. - Elf_Sym* FindSymbolByName(Elf_Word section_type, - const std::string& symbol_name, - bool build_map); - Elf_Phdr* FindProgamHeaderByType(Elf_Word type) const; // Lookup a string by section type. Returns null for special 0 offset. const char* GetString(Elf_Word section_type, Elf_Word) const; const std::string file_path_; - const bool writable_; - const bool program_header_only_; // ELF header mapping. If program_header_only_ is false, will // actually point to the entire elf file. @@ -200,9 +156,6 @@ class ElfFileImpl { char* dynstr_section_start_; Elf_Word* hash_section_start_; - SymbolTable* symtab_symbol_table_; - SymbolTable* dynsym_symbol_table_; - DISALLOW_COPY_AND_ASSIGN(ElfFileImpl); }; diff --git a/runtime/oat/oat_file.cc b/runtime/oat/oat_file.cc index 063b0b55ad..6679d23aff 100644 --- a/runtime/oat/oat_file.cc +++ b/runtime/oat/oat_file.cc @@ -152,7 +152,6 @@ class OatFileBase : public OatFile { const std::string& vdex_filename, const std::string& elf_filename, const std::string& location, - bool writable, bool executable, bool low_4gb, ArrayRef<const std::string> dex_filenames, @@ -166,7 +165,6 @@ class OatFileBase : public OatFile { int oat_fd, const std::string& vdex_filename, const std::string& oat_filename, - bool writable, bool executable, bool low_4gb, ArrayRef<const std::string> dex_filenames, @@ -182,30 +180,24 @@ class OatFileBase : public OatFile { virtual void PreLoad() = 0; - bool LoadVdex(const std::string& vdex_filename, - bool writable, - bool low_4gb, - std::string* error_msg); + bool LoadVdex(const std::string& vdex_filename, bool low_4gb, std::string* error_msg); bool LoadVdex(int vdex_fd, const std::string& vdex_filename, - bool writable, bool low_4gb, std::string* error_msg); virtual bool Load(const std::string& elf_filename, - bool writable, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, // Where to load if not null. - /*out*/std::string* error_msg) = 0; + /*inout*/ MemMap* reservation, // Where to load if not null. + /*out*/ std::string* error_msg) = 0; virtual bool Load(int oat_fd, - bool writable, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, // Where to load if not null. - /*out*/std::string* error_msg) = 0; + /*inout*/ MemMap* reservation, // Where to load if not null. + /*out*/ std::string* error_msg) = 0; bool ComputeFields(const std::string& file_path, std::string* error_msg); @@ -256,7 +248,6 @@ OatFileBase* OatFileBase::OpenOatFile(int zip_fd, const std::string& vdex_filename, const std::string& elf_filename, const std::string& location, - bool writable, bool executable, bool low_4gb, ArrayRef<const std::string> dex_filenames, @@ -267,12 +258,7 @@ OatFileBase* OatFileBase::OpenOatFile(int zip_fd, ret->PreLoad(); - if (!ret->Load(elf_filename, - writable, - executable, - low_4gb, - reservation, - error_msg)) { + if (!ret->Load(elf_filename, executable, low_4gb, reservation, error_msg)) { return nullptr; } @@ -282,7 +268,7 @@ OatFileBase* OatFileBase::OpenOatFile(int zip_fd, ret->PreSetup(elf_filename); - if (!ret->LoadVdex(vdex_filename, writable, low_4gb, error_msg)) { + if (!ret->LoadVdex(vdex_filename, low_4gb, error_msg)) { return nullptr; } @@ -299,7 +285,6 @@ OatFileBase* OatFileBase::OpenOatFile(int zip_fd, int oat_fd, const std::string& vdex_location, const std::string& oat_location, - bool writable, bool executable, bool low_4gb, ArrayRef<const std::string> dex_filenames, @@ -308,12 +293,7 @@ OatFileBase* OatFileBase::OpenOatFile(int zip_fd, /*out*/ std::string* error_msg) { std::unique_ptr<OatFileBase> ret(new kOatFileBaseSubType(oat_location, executable)); - if (!ret->Load(oat_fd, - writable, - executable, - low_4gb, - reservation, - error_msg)) { + if (!ret->Load(oat_fd, executable, low_4gb, reservation, error_msg)) { return nullptr; } @@ -323,7 +303,7 @@ OatFileBase* OatFileBase::OpenOatFile(int zip_fd, ret->PreSetup(oat_location); - if (!ret->LoadVdex(vdex_fd, vdex_location, writable, low_4gb, error_msg)) { + if (!ret->LoadVdex(vdex_fd, vdex_location, low_4gb, error_msg)) { return nullptr; } @@ -334,15 +314,11 @@ OatFileBase* OatFileBase::OpenOatFile(int zip_fd, return ret.release(); } -bool OatFileBase::LoadVdex(const std::string& vdex_filename, - bool writable, - bool low_4gb, - std::string* error_msg) { +bool OatFileBase::LoadVdex(const std::string& vdex_filename, bool low_4gb, std::string* error_msg) { vdex_ = VdexFile::OpenAtAddress(vdex_begin_, vdex_end_ - vdex_begin_, /*mmap_reuse=*/vdex_begin_ != nullptr, vdex_filename, - writable, low_4gb, error_msg); if (vdex_.get() == nullptr) { @@ -356,7 +332,6 @@ bool OatFileBase::LoadVdex(const std::string& vdex_filename, bool OatFileBase::LoadVdex(int vdex_fd, const std::string& vdex_filename, - bool writable, bool low_4gb, std::string* error_msg) { if (vdex_fd != -1) { @@ -371,7 +346,6 @@ bool OatFileBase::LoadVdex(int vdex_fd, vdex_fd, s.st_size, vdex_filename, - writable, low_4gb, error_msg); if (vdex_.get() == nullptr) { @@ -1193,14 +1167,12 @@ class DlOpenOatFile final : public OatFileBase { void PreLoad() override; bool Load(const std::string& elf_filename, - bool writable, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, // Where to load if not null. - /*out*/std::string* error_msg) override; + /*inout*/ MemMap* reservation, // Where to load if not null. + /*out*/ std::string* error_msg) override; bool Load([[maybe_unused]] int oat_fd, - [[maybe_unused]] bool writable, [[maybe_unused]] bool executable, [[maybe_unused]] bool low_4gb, [[maybe_unused]] /*inout*/ MemMap* reservation, @@ -1276,11 +1248,10 @@ void DlOpenOatFile::PreLoad() { } bool DlOpenOatFile::Load(const std::string& elf_filename, - bool writable, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, // Where to load if not null. - /*out*/std::string* error_msg) { + /*inout*/ MemMap* reservation, // Where to load if not null. + /*out*/ std::string* error_msg) { // Use dlopen only when flagged to do so, and when it's OK to load things executable. // TODO: Also try when not executable? The issue here could be re-mapping as writable (as // !executable is a sign that we may want to patch), which may not be allowed for @@ -1293,10 +1264,6 @@ bool DlOpenOatFile::Load(const std::string& elf_filename, *error_msg = "DlOpen does not support low 4gb loading."; return false; } - if (writable) { - *error_msg = "DlOpen does not support writable loading."; - return false; - } if (!executable) { *error_msg = "DlOpen does not support non-executable loading."; return false; @@ -1636,18 +1603,16 @@ class ElfOatFile final : public OatFileBase { } bool Load(const std::string& elf_filename, - bool writable, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, // Where to load if not null. - /*out*/std::string* error_msg) override; + /*inout*/ MemMap* reservation, // Where to load if not null. + /*out*/ std::string* error_msg) override; bool Load(int oat_fd, - bool writable, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, // Where to load if not null. - /*out*/std::string* error_msg) override; + /*inout*/ MemMap* reservation, // Where to load if not null. + /*out*/ std::string* error_msg) override; void PreSetup([[maybe_unused]] const std::string& elf_filename) override {} @@ -1657,11 +1622,10 @@ class ElfOatFile final : public OatFileBase { private: bool ElfFileOpen(File* file, - bool writable, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, // Where to load if not null. - /*out*/std::string* error_msg); + /*inout*/ MemMap* reservation, // Where to load if not null. + /*out*/ std::string* error_msg); private: // Backing memory map for oat file during cross compilation. @@ -1671,31 +1635,24 @@ class ElfOatFile final : public OatFileBase { }; bool ElfOatFile::Load(const std::string& elf_filename, - bool writable, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, - /*out*/std::string* error_msg) { + /*inout*/ MemMap* reservation, + /*out*/ std::string* error_msg) { ScopedTrace trace(__PRETTY_FUNCTION__); std::unique_ptr<File> file(OS::OpenFileForReading(elf_filename.c_str())); if (file == nullptr) { *error_msg = StringPrintf("Failed to open oat filename for reading: %s", strerror(errno)); return false; } - return ElfOatFile::ElfFileOpen(file.get(), - writable, - executable, - low_4gb, - reservation, - error_msg); + return ElfOatFile::ElfFileOpen(file.get(), executable, low_4gb, reservation, error_msg); } bool ElfOatFile::Load(int oat_fd, - bool writable, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, - /*out*/std::string* error_msg) { + /*inout*/ MemMap* reservation, + /*out*/ std::string* error_msg) { ScopedTrace trace(__PRETTY_FUNCTION__); if (oat_fd != -1) { int duped_fd = DupCloexec(oat_fd); @@ -1705,28 +1662,18 @@ bool ElfOatFile::Load(int oat_fd, strerror(errno)); return false; } - return ElfOatFile::ElfFileOpen(file.get(), - writable, - executable, - low_4gb, - reservation, - error_msg); + return ElfOatFile::ElfFileOpen(file.get(), executable, low_4gb, reservation, error_msg); } return false; } bool ElfOatFile::ElfFileOpen(File* file, - bool writable, bool executable, bool low_4gb, - /*inout*/MemMap* reservation, - /*out*/std::string* error_msg) { + /*inout*/ MemMap* reservation, + /*out*/ std::string* error_msg) { ScopedTrace trace(__PRETTY_FUNCTION__); - elf_file_.reset(ElfFile::Open(file, - writable, - /*program_header_only=*/true, - low_4gb, - error_msg)); + elf_file_.reset(ElfFile::Open(file, low_4gb, error_msg)); if (elf_file_ == nullptr) { DCHECK(!error_msg->empty()); return false; @@ -1901,7 +1848,6 @@ class OatFileBackedByVdex final : public OatFileBase { void PreLoad() override {} bool Load([[maybe_unused]] const std::string& elf_filename, - [[maybe_unused]] bool writable, [[maybe_unused]] bool executable, [[maybe_unused]] bool low_4gb, [[maybe_unused]] MemMap* reservation, @@ -1911,7 +1857,6 @@ class OatFileBackedByVdex final : public OatFileBase { } bool Load([[maybe_unused]] int oat_fd, - [[maybe_unused]] bool writable, [[maybe_unused]] bool executable, [[maybe_unused]] bool low_4gb, [[maybe_unused]] MemMap* reservation, @@ -1977,7 +1922,6 @@ OatFile* OatFile::Open(int zip_fd, vdex_filename, oat_filename, oat_location, - /*writable=*/false, executable, low_4gb, dex_filenames, @@ -2007,7 +1951,6 @@ OatFile* OatFile::Open(int zip_fd, vdex_filename, oat_filename, oat_location, - /*writable=*/false, executable, low_4gb, dex_filenames, @@ -2036,7 +1979,6 @@ OatFile* OatFile::Open(int zip_fd, oat_fd, vdex_location, oat_location, - /*writable=*/false, executable, low_4gb, dex_filenames, diff --git a/runtime/oat/oat_file_assistant.cc b/runtime/oat/oat_file_assistant.cc index be145d8ce1..8e4405d05d 100644 --- a/runtime/oat/oat_file_assistant.cc +++ b/runtime/oat/oat_file_assistant.cc @@ -1019,14 +1019,12 @@ const OatFile* OatFileAssistant::OatFileInfo::GetFile() { vdex = VdexFile::Open(vdex_fd_, s.st_size, filename_, - /*writable=*/false, /*low_4gb=*/false, &error_msg); } } } else { vdex = VdexFile::Open(filename_, - /*writable=*/false, /*low_4gb=*/false, &error_msg); } diff --git a/runtime/oat/oat_file_manager.cc b/runtime/oat/oat_file_manager.cc index 320961755f..cf54837d44 100644 --- a/runtime/oat/oat_file_manager.cc +++ b/runtime/oat/oat_file_manager.cc @@ -555,8 +555,7 @@ std::vector<std::unique_ptr<const DexFile>> OatFileManager::OpenDexFilesFromOat_ std::unique_ptr<VdexFile> vdex_file = nullptr; if (has_vdex && OS::FileExists(vdex_path.c_str())) { vdex_file = VdexFile::Open(vdex_path, - /* writable= */ false, - /* low_4gb= */ false, + /*low_4gb=*/false, &error_msg); if (vdex_file == nullptr) { LOG(WARNING) << "Failed to open vdex " << vdex_path << ": " << error_msg; diff --git a/runtime/runtime_test.cc b/runtime/runtime_test.cc index 182a992434..3360b3b558 100644 --- a/runtime/runtime_test.cc +++ b/runtime/runtime_test.cc @@ -102,8 +102,6 @@ TEST_F(RuntimeTest, ElfAlignmentMismatch) { std::string error_msg; std::unique_ptr<ElfFile> elf_file(ElfFile::Open(core_oat_file.get(), - /*writable=*/false, - /*program_header_only=*/true, /*low_4gb=*/false, &error_msg)); ASSERT_TRUE(elf_file != nullptr) << error_msg; diff --git a/runtime/vdex_file.cc b/runtime/vdex_file.cc index db2a976c22..7090320fc4 100644 --- a/runtime/vdex_file.cc +++ b/runtime/vdex_file.cc @@ -68,7 +68,6 @@ std::unique_ptr<VdexFile> VdexFile::OpenAtAddress(uint8_t* mmap_addr, size_t mmap_size, bool mmap_reuse, const std::string& vdex_filename, - bool writable, bool low_4gb, std::string* error_msg) { ScopedTrace trace(("VdexFile::OpenAtAddress " + vdex_filename).c_str()); @@ -77,15 +76,9 @@ std::unique_ptr<VdexFile> VdexFile::OpenAtAddress(uint8_t* mmap_addr, return nullptr; } - std::unique_ptr<File> vdex_file; - if (writable) { - vdex_file.reset(OS::OpenFileReadWrite(vdex_filename.c_str())); - } else { - vdex_file.reset(OS::OpenFileForReading(vdex_filename.c_str())); - } + std::unique_ptr<File> vdex_file(OS::OpenFileForReading(vdex_filename.c_str())); if (vdex_file == nullptr) { - *error_msg = "Could not open file " + vdex_filename + - (writable ? " for read/write" : "for reading"); + *error_msg = "Could not open file for reading"; return nullptr; } @@ -101,7 +94,6 @@ std::unique_ptr<VdexFile> VdexFile::OpenAtAddress(uint8_t* mmap_addr, vdex_file->Fd(), vdex_length, vdex_filename, - writable, low_4gb, error_msg); } @@ -112,7 +104,6 @@ std::unique_ptr<VdexFile> VdexFile::OpenAtAddress(uint8_t* mmap_addr, int file_fd, size_t vdex_length, const std::string& vdex_filename, - bool writable, bool low_4gb, std::string* error_msg) { if (mmap_addr != nullptr && mmap_size < vdex_length) { @@ -123,18 +114,17 @@ std::unique_ptr<VdexFile> VdexFile::OpenAtAddress(uint8_t* mmap_addr, } CHECK_IMPLIES(mmap_reuse, mmap_addr != nullptr); // Start as PROT_WRITE so we can mprotect back to it if we want to. - MemMap mmap = MemMap::MapFileAtAddress( - mmap_addr, - vdex_length, - PROT_READ | PROT_WRITE, - writable ? MAP_SHARED : MAP_PRIVATE, - file_fd, - /* start= */ 0u, - low_4gb, - vdex_filename.c_str(), - mmap_reuse, - /* reservation= */ nullptr, - error_msg); + MemMap mmap = MemMap::MapFileAtAddress(mmap_addr, + vdex_length, + PROT_READ | PROT_WRITE, + MAP_PRIVATE, + file_fd, + /*start=*/0u, + low_4gb, + vdex_filename.c_str(), + mmap_reuse, + /*reservation=*/nullptr, + error_msg); if (!mmap.IsValid()) { *error_msg = "Failed to mmap file " + vdex_filename + " : " + *error_msg; return nullptr; diff --git a/runtime/vdex_file.h b/runtime/vdex_file.h index 4a1665b34d..7bfbbd169a 100644 --- a/runtime/vdex_file.h +++ b/runtime/vdex_file.h @@ -191,7 +191,6 @@ class VdexFile { size_t mmap_size, bool mmap_reuse, const std::string& vdex_filename, - bool writable, bool low_4gb, std::string* error_msg); @@ -203,40 +202,24 @@ class VdexFile { int file_fd, size_t vdex_length, const std::string& vdex_filename, - bool writable, bool low_4gb, std::string* error_msg); // Returns nullptr if the vdex file cannot be opened or is not valid. static std::unique_ptr<VdexFile> Open(const std::string& vdex_filename, - bool writable, bool low_4gb, std::string* error_msg) { - return OpenAtAddress(nullptr, - 0, - false, - vdex_filename, - writable, - low_4gb, - error_msg); + return OpenAtAddress(nullptr, 0, false, vdex_filename, low_4gb, error_msg); } // Returns nullptr if the vdex file cannot be opened or is not valid. static std::unique_ptr<VdexFile> Open(int file_fd, size_t vdex_length, const std::string& vdex_filename, - bool writable, bool low_4gb, std::string* error_msg) { - return OpenAtAddress(nullptr, - 0, - false, - file_fd, - vdex_length, - vdex_filename, - writable, - low_4gb, - error_msg); + return OpenAtAddress( + nullptr, 0, false, file_fd, vdex_length, vdex_filename, low_4gb, error_msg); } EXPORT static std::unique_ptr<VdexFile> OpenFromDm(const std::string& filename, diff --git a/runtime/vdex_file_test.cc b/runtime/vdex_file_test.cc index 4c359e38c6..fb0c03aa6a 100644 --- a/runtime/vdex_file_test.cc +++ b/runtime/vdex_file_test.cc @@ -33,13 +33,11 @@ TEST_F(VdexFileTest, OpenEmptyVdex) { std::unique_ptr<VdexFile> vdex = VdexFile::Open(tmp.GetFd(), 0, tmp.GetFilename(), - /*writable=*/false, /*low_4gb=*/false, &error_msg); EXPECT_TRUE(vdex == nullptr); - vdex = VdexFile::Open( - tmp.GetFilename(), /*writable=*/false, /*low_4gb=*/false, &error_msg); + vdex = VdexFile::Open(tmp.GetFilename(), /*low_4gb=*/false, &error_msg); EXPECT_TRUE(vdex == nullptr); } |