summaryrefslogtreecommitdiffstats
path: root/runtime
diff options
context:
space:
mode:
Diffstat (limited to 'runtime')
-rw-r--r--runtime/class_linker.cc13
-rw-r--r--runtime/elf_file.cc85
-rw-r--r--runtime/elf_file_impl.h9
-rw-r--r--runtime/gc/heap.cc1
-rw-r--r--runtime/gc/space/image_space.cc5
-rw-r--r--runtime/gc/space/image_space.h4
-rw-r--r--runtime/mem_map.cc8
-rw-r--r--runtime/mem_map.h6
-rw-r--r--runtime/native/dalvik_system_ZygoteHooks.cc10
-rw-r--r--runtime/oat_file.cc61
-rw-r--r--runtime/oat_file.h3
11 files changed, 120 insertions, 85 deletions
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 91812e7..ae952e6 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -808,18 +808,11 @@ static void FreeDexFilesInHeap(std::priority_queue<DexFileAndClassPair>* heap) {
}
const OatFile* ClassLinker::GetBootOatFile() {
- // To grab the boot oat, look at the dex files in the boot classpath. Any of those is fine, as
- // they were all compiled into the same oat file. So grab the first one, which is guaranteed to
- // exist if the boot class-path isn't empty.
- if (boot_class_path_.empty()) {
+ gc::space::ImageSpace* image_space = Runtime::Current()->GetHeap()->GetImageSpace();
+ if (image_space == nullptr) {
return nullptr;
}
- const DexFile* boot_dex_file = boot_class_path_[0];
- // Is it from an oat file?
- if (boot_dex_file->GetOatDexFile() != nullptr) {
- return boot_dex_file->GetOatDexFile()->GetOatFile();
- }
- return nullptr;
+ return image_space->GetOatFile();
}
const OatFile* ClassLinker::GetPrimaryOatFile() {
diff --git a/runtime/elf_file.cc b/runtime/elf_file.cc
index 0c5210d..9fd8c87 100644
--- a/runtime/elf_file.cc
+++ b/runtime/elf_file.cc
@@ -1401,88 +1401,53 @@ typename ElfTypes::Shdr* ElfFileImpl<ElfTypes>::FindSectionByName(
}
template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta) {
- const Elf_Shdr* debug_info = FindSectionByName(".debug_info");
- const Elf_Shdr* debug_abbrev = FindSectionByName(".debug_abbrev");
- const Elf_Shdr* debug_str = FindSectionByName(".debug_str");
- const Elf_Shdr* strtab_sec = FindSectionByName(".strtab");
- const Elf_Shdr* symtab_sec = FindSectionByName(".symtab");
-
- if (debug_info == nullptr || debug_abbrev == nullptr ||
- debug_str == nullptr || strtab_sec == nullptr || symtab_sec == nullptr) {
- // Release version of ART does not generate debug info.
- return true;
- }
+bool ElfFileImpl<ElfTypes>::FixupDebugSections(Elf_Addr base_address_delta) {
if (base_address_delta == 0) {
return true;
}
- if (!ApplyOatPatchesTo(".debug_info", base_address_delta)) {
- return false;
- }
- if (!ApplyOatPatchesTo(".debug_line", base_address_delta)) {
- return false;
- }
- return true;
+ return ApplyOatPatchesTo(".debug_frame", base_address_delta) &&
+ ApplyOatPatchesTo(".debug_info", base_address_delta) &&
+ ApplyOatPatchesTo(".debug_line", base_address_delta);
}
template <typename ElfTypes>
bool ElfFileImpl<ElfTypes>::ApplyOatPatchesTo(
- const char* target_section_name,
- typename std::make_signed<Elf_Off>::type delta) {
- auto patches_section = FindSectionByName(".oat_patches");
+ const char* target_section_name, Elf_Addr delta) {
+ auto target_section = FindSectionByName(target_section_name);
+ if (target_section == nullptr) {
+ return true;
+ }
+ std::string patches_name = target_section_name + std::string(".oat_patches");
+ auto patches_section = FindSectionByName(patches_name.c_str());
if (patches_section == nullptr) {
- LOG(ERROR) << ".oat_patches section not found.";
+ LOG(ERROR) << patches_name << " section not found.";
return false;
}
if (patches_section->sh_type != SHT_OAT_PATCH) {
- LOG(ERROR) << "Unexpected type of .oat_patches.";
- return false;
- }
- auto target_section = FindSectionByName(target_section_name);
- if (target_section == nullptr) {
- LOG(ERROR) << target_section_name << " section not found.";
+ LOG(ERROR) << "Unexpected type of " << patches_name;
return false;
}
- if (!ApplyOatPatches(
+ ApplyOatPatches(
Begin() + patches_section->sh_offset,
Begin() + patches_section->sh_offset + patches_section->sh_size,
- target_section_name, delta,
+ delta,
Begin() + target_section->sh_offset,
- Begin() + target_section->sh_offset + target_section->sh_size)) {
- LOG(ERROR) << target_section_name << " section not found in .oat_patches.";
- }
+ Begin() + target_section->sh_offset + target_section->sh_size);
return true;
}
-// Apply .oat_patches to given section.
+// Apply LEB128 encoded patches to given section.
template <typename ElfTypes>
-bool ElfFileImpl<ElfTypes>::ApplyOatPatches(
- const uint8_t* patches, const uint8_t* patches_end,
- const char* target_section_name,
- typename std::make_signed<Elf_Off>::type delta,
+void ElfFileImpl<ElfTypes>::ApplyOatPatches(
+ const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
uint8_t* to_patch, const uint8_t* to_patch_end) {
- // Read null-terminated section name.
- const char* section_name;
- while ((section_name = reinterpret_cast<const char*>(patches))[0] != '\0') {
- patches += strlen(section_name) + 1;
- uint32_t length = DecodeUnsignedLeb128(&patches);
- const uint8_t* next_section = patches + length;
- // Is it the section we want to patch?
- if (strcmp(section_name, target_section_name) == 0) {
- // Read LEB128 encoded list of advances.
- while (patches < next_section) {
- DCHECK_LT(patches, patches_end) << "Unexpected end of .oat_patches.";
- to_patch += DecodeUnsignedLeb128(&patches);
- DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of " << section_name;
- // TODO: 32-bit vs 64-bit. What is the right type to use here?
- auto* patch_loc = reinterpret_cast<typename std::make_signed<Elf_Off>::type*>(to_patch);
- *patch_loc += delta;
- }
- return true;
- }
- patches = next_section;
+ typedef __attribute__((__aligned__(1))) Elf_Addr UnalignedAddress;
+ while (patches < patches_end) {
+ to_patch += DecodeUnsignedLeb128(&patches);
+ DCHECK_LE(patches, patches_end) << "Unexpected end of patch list.";
+ DCHECK_LT(to_patch, to_patch_end) << "Patch past the end of section.";
+ *reinterpret_cast<UnalignedAddress*>(to_patch) += delta;
}
- return false;
}
template <typename ElfTypes>
diff --git a/runtime/elf_file_impl.h b/runtime/elf_file_impl.h
index 3ad096f..0f466bd 100644
--- a/runtime/elf_file_impl.h
+++ b/runtime/elf_file_impl.h
@@ -119,12 +119,9 @@ class ElfFileImpl {
bool FixupProgramHeaders(Elf_Addr base_address);
bool FixupSymbols(Elf_Addr base_address, bool dynamic);
bool FixupRelocations(Elf_Addr base_address);
- bool FixupDebugSections(typename std::make_signed<Elf_Off>::type base_address_delta);
- bool ApplyOatPatchesTo(const char* target_section_name,
- typename std::make_signed<Elf_Off>::type base_address_delta);
- static bool ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end,
- const char* target_section_name,
- typename std::make_signed<Elf_Off>::type delta,
+ bool FixupDebugSections(Elf_Addr base_address_delta);
+ bool ApplyOatPatchesTo(const char* target_section_name, Elf_Addr base_address_delta);
+ static void ApplyOatPatches(const uint8_t* patches, const uint8_t* patches_end, Elf_Addr delta,
uint8_t* to_patch, const uint8_t* to_patch_end);
bool Strip(std::string* error_msg);
diff --git a/runtime/gc/heap.cc b/runtime/gc/heap.cc
index eabbbec..9a70d69 100644
--- a/runtime/gc/heap.cc
+++ b/runtime/gc/heap.cc
@@ -502,6 +502,7 @@ Heap::Heap(size_t initial_size, size_t growth_limit, size_t min_free, size_t max
bool no_gap = MemMap::CheckNoGaps(GetImageSpace()->GetMemMap(),
non_moving_space_->GetMemMap());
if (!no_gap) {
+ PrintFileToLog("/proc/self/maps", LogSeverity::ERROR);
MemMap::DumpMaps(LOG(ERROR), true);
LOG(FATAL) << "There's a gap between the image space and the non-moving space";
}
diff --git a/runtime/gc/space/image_space.cc b/runtime/gc/space/image_space.cc
index f7ceb84..1923d24 100644
--- a/runtime/gc/space/image_space.cc
+++ b/runtime/gc/space/image_space.cc
@@ -755,6 +755,7 @@ ImageSpace* ImageSpace::Init(const char* image_filename, const char* image_locat
DCHECK(!error_msg->empty());
return nullptr;
}
+ space->oat_file_non_owned_ = space->oat_file_.get();
if (validate_oat_file && !space->ValidateOatFile(error_msg)) {
DCHECK(!error_msg->empty());
@@ -838,10 +839,12 @@ bool ImageSpace::ValidateOatFile(std::string* error_msg) const {
return true;
}
+
const OatFile* ImageSpace::GetOatFile() const {
- return oat_file_.get();
+ return oat_file_non_owned_;
}
+
OatFile* ImageSpace::ReleaseOatFile() {
CHECK(oat_file_.get() != nullptr);
return oat_file_.release();
diff --git a/runtime/gc/space/image_space.h b/runtime/gc/space/image_space.h
index 54dc7a6..93ff8aa 100644
--- a/runtime/gc/space/image_space.h
+++ b/runtime/gc/space/image_space.h
@@ -152,6 +152,10 @@ class ImageSpace : public MemMapSpace {
// the ClassLinker during it's initialization.
std::unique_ptr<OatFile> oat_file_;
+ // There are times when we need to find the boot image oat file. As
+ // we release ownership during startup, keep a non-owned reference.
+ const OatFile* oat_file_non_owned_;
+
const std::string image_location_;
DISALLOW_COPY_AND_ASSIGN(ImageSpace);
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc
index d6d71f2..6566060 100644
--- a/runtime/mem_map.cc
+++ b/runtime/mem_map.cc
@@ -439,6 +439,14 @@ MemMap* MemMap::MapAnonymous(const char* name, uint8_t* expected_ptr, size_t byt
page_aligned_byte_count, prot, false);
}
+MemMap* MemMap::MapDummy(const char* name, uint8_t* addr, size_t byte_count) {
+ if (byte_count == 0) {
+ return new MemMap(name, nullptr, 0, nullptr, 0, 0, false);
+ }
+ const size_t page_aligned_byte_count = RoundUp(byte_count, kPageSize);
+ return new MemMap(name, addr, byte_count, addr, page_aligned_byte_count, 0, true /* reuse */);
+}
+
MemMap* MemMap::MapFileAtAddress(uint8_t* expected_ptr, size_t byte_count, int prot, int flags,
int fd, off_t start, bool reuse, const char* filename,
std::string* error_msg) {
diff --git a/runtime/mem_map.h b/runtime/mem_map.h
index 6023a70..14387ee 100644
--- a/runtime/mem_map.h
+++ b/runtime/mem_map.h
@@ -64,6 +64,12 @@ class MemMap {
static MemMap* MapAnonymous(const char* ashmem_name, uint8_t* addr, size_t byte_count, int prot,
bool low_4gb, bool reuse, std::string* error_msg);
+ // Create placeholder for a region allocated by direct call to mmap.
+ // This is useful when we do not have control over the code calling mmap,
+ // but when we still want to keep track of it in the list.
+ // The region is not considered to be owned and will not be unmmaped.
+ static MemMap* MapDummy(const char* name, uint8_t* addr, size_t byte_count);
+
// Map part of a file, taking care of non-page aligned offsets. The
// "start" offset is absolute, not relative.
//
diff --git a/runtime/native/dalvik_system_ZygoteHooks.cc b/runtime/native/dalvik_system_ZygoteHooks.cc
index 1a7a3e5..1d06706 100644
--- a/runtime/native/dalvik_system_ZygoteHooks.cc
+++ b/runtime/native/dalvik_system_ZygoteHooks.cc
@@ -65,7 +65,7 @@ static void EnableDebugFeatures(uint32_t debug_flags) {
DEBUG_ENABLE_SAFEMODE = 1 << 3,
DEBUG_ENABLE_JNI_LOGGING = 1 << 4,
DEBUG_ENABLE_JIT = 1 << 5,
- DEBUG_GENERATE_CFI = 1 << 6,
+ DEBUG_GENERATE_DEBUG_INFO = 1 << 6,
};
Runtime* const runtime = Runtime::Current();
@@ -112,10 +112,10 @@ static void EnableDebugFeatures(uint32_t debug_flags) {
}
runtime->GetJITOptions()->SetUseJIT(use_jit);
- const bool generate_cfi = (debug_flags & DEBUG_GENERATE_CFI) != 0;
- if (generate_cfi) {
- runtime->AddCompilerOption("--include-cfi");
- debug_flags &= ~DEBUG_GENERATE_CFI;
+ const bool generate_debug_info = (debug_flags & DEBUG_GENERATE_DEBUG_INFO) != 0;
+ if (generate_debug_info) {
+ runtime->AddCompilerOption("--generate-debug-info");
+ debug_flags &= ~DEBUG_GENERATE_DEBUG_INFO;
}
// This is for backwards compatibility with Dalvik.
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 6fda790..ad5741e 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -21,6 +21,9 @@
#include <unistd.h>
#include <cstdlib>
+#ifndef __APPLE__
+#include <link.h> // for dl_iterate_phdr.
+#endif
#include <sstream>
// dlopen_ext support from bionic.
@@ -35,6 +38,7 @@
#include "elf_file.h"
#include "elf_utils.h"
#include "oat.h"
+#include "mem_map.h"
#include "mirror/class.h"
#include "mirror/object-inl.h"
#include "os.h"
@@ -45,13 +49,13 @@
namespace art {
// Whether OatFile::Open will try DlOpen() first. Fallback is our own ELF loader.
-static constexpr bool kUseDlopen = false;
+static constexpr bool kUseDlopen = true;
// Whether OatFile::Open will try DlOpen() on the host. On the host we're not linking against
// bionic, so cannot take advantage of the support for changed semantics (loading the same soname
// multiple times). However, if/when we switch the above, we likely want to switch this, too,
// to get test coverage of the code paths.
-static constexpr bool kUseDlopenOnHost = false;
+static constexpr bool kUseDlopenOnHost = true;
// For debugging, Open will print DlOpen error message if set to true.
static constexpr bool kPrintDlOpenErrorMessage = false;
@@ -210,6 +214,15 @@ OatFile::~OatFile() {
bool OatFile::Dlopen(const std::string& elf_filename, uint8_t* requested_base,
const char* abs_dex_location, std::string* error_msg) {
+#ifdef __APPLE__
+ // The dl_iterate_phdr syscall is missing. There is similar API on OSX,
+ // but let's fallback to the custom loading code for the time being.
+ UNUSED(elf_filename);
+ UNUSED(requested_base);
+ UNUSED(abs_dex_location);
+ UNUSED(error_msg);
+ return false;
+#else
std::unique_ptr<char> absolute_path(realpath(elf_filename.c_str(), nullptr));
if (absolute_path == nullptr) {
*error_msg = StringPrintf("Failed to find absolute path for '%s'", elf_filename.c_str());
@@ -217,7 +230,7 @@ bool OatFile::Dlopen(const std::string& elf_filename, uint8_t* requested_base,
}
#ifdef HAVE_ANDROID_OS
android_dlextinfo extinfo;
- extinfo.flags = ANDROID_DLEXT_FORCE_LOAD;
+ extinfo.flags = ANDROID_DLEXT_FORCE_LOAD | ANDROID_DLEXT_FORCE_FIXED_VADDR;
dlopen_handle_ = android_dlopen_ext(absolute_path.get(), RTLD_NOW, &extinfo);
#else
dlopen_handle_ = dlopen(absolute_path.get(), RTLD_NOW);
@@ -264,7 +277,49 @@ bool OatFile::Dlopen(const std::string& elf_filename, uint8_t* requested_base,
bss_end_ += sizeof(uint32_t);
}
+ // Ask the linker where it mmaped the file and notify our mmap wrapper of the regions.
+ struct dl_iterate_context {
+ static int callback(struct dl_phdr_info *info, size_t /* size */, void *data) {
+ auto* context = reinterpret_cast<dl_iterate_context*>(data);
+ // See whether this callback corresponds to the file which we have just loaded.
+ bool contains_begin = false;
+ for (int i = 0; i < info->dlpi_phnum; i++) {
+ if (info->dlpi_phdr[i].p_type == PT_LOAD) {
+ uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
+ info->dlpi_phdr[i].p_vaddr);
+ size_t memsz = info->dlpi_phdr[i].p_memsz;
+ if (vaddr <= context->begin_ && context->begin_ < vaddr + memsz) {
+ contains_begin = true;
+ break;
+ }
+ }
+ }
+ // Add dummy mmaps for this file.
+ if (contains_begin) {
+ for (int i = 0; i < info->dlpi_phnum; i++) {
+ if (info->dlpi_phdr[i].p_type == PT_LOAD) {
+ uint8_t* vaddr = reinterpret_cast<uint8_t*>(info->dlpi_addr +
+ info->dlpi_phdr[i].p_vaddr);
+ size_t memsz = info->dlpi_phdr[i].p_memsz;
+ MemMap* mmap = MemMap::MapDummy(info->dlpi_name, vaddr, memsz);
+ context->dlopen_mmaps_->push_back(std::unique_ptr<MemMap>(mmap));
+ }
+ }
+ return 1; // Stop iteration and return 1 from dl_iterate_phdr.
+ }
+ return 0; // Continue iteration and return 0 from dl_iterate_phdr when finished.
+ }
+ const uint8_t* const begin_;
+ std::vector<std::unique_ptr<MemMap>>* const dlopen_mmaps_;
+ } context = { begin_, &dlopen_mmaps_ };
+
+ if (dl_iterate_phdr(dl_iterate_context::callback, &context) == 0) {
+ PrintFileToLog("/proc/self/maps", LogSeverity::WARNING);
+ LOG(ERROR) << "File " << elf_filename << " loaded with dlopen but can not find its mmaps.";
+ }
+
return Setup(abs_dex_location, error_msg);
+#endif // __APPLE__
}
bool OatFile::ElfFileOpen(File* file, uint8_t* requested_base, uint8_t* oat_file_begin,
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index c58b029..1a782de 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -321,6 +321,9 @@ class OatFile FINAL {
// dlopen handle during runtime.
void* dlopen_handle_;
+ // Dummy memory map objects corresponding to the regions mapped by dlopen.
+ std::vector<std::unique_ptr<MemMap>> dlopen_mmaps_;
+
// Owning storage for the OatDexFile objects.
std::vector<const OatDexFile*> oat_dex_files_storage_;