summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dex2oat/Android.bp4
-rw-r--r--dex2oat/dex2oat.cc6
-rw-r--r--dex2oat/dex2oat_test.cc4
-rw-r--r--dex2oat/dex2oat_vdex_test.cc1
-rw-r--r--dex2oat/linker/elf_writer_test.cc135
-rw-r--r--runtime/oat/elf_file.cc655
-rw-r--r--runtime/oat/elf_file.h28
-rw-r--r--runtime/oat/elf_file_impl.h51
-rw-r--r--runtime/oat/oat_file.cc116
-rw-r--r--runtime/oat/oat_file_assistant.cc2
-rw-r--r--runtime/oat/oat_file_manager.cc3
-rw-r--r--runtime/runtime_test.cc2
-rw-r--r--runtime/vdex_file.cc36
-rw-r--r--runtime/vdex_file.h23
-rw-r--r--runtime/vdex_file_test.cc4
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", &section_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);
}