From 1baabf0726eb285284e0c908ccba9f209b399fae Mon Sep 17 00:00:00 2001 From: David Srbecky Date: Tue, 16 Jun 2015 17:12:34 +0000 Subject: [PATCH] Revert "Revert "Use dlopen to load oat files."" This reverts commit 7a46b7e235a7c35191cd9ddbab6ca4db0e535da5. Change-Id: I33439d0e3d7a7e63591a8c7b356e716dcb62bca1 --- runtime/mem_map.cc | 8 ++++++++ runtime/mem_map.h | 6 ++++++ runtime/oat_file.cc | 39 ++++++++++++++++++++++++++++++++++++--- test/137-cfi/run | 21 +++++++++++++++++++++ test/137-cfi/src/Main.java | 2 +- 5 files changed, 72 insertions(+), 4 deletions(-) create mode 100755 test/137-cfi/run diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc index 189306df5..fa041a996 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 6023a703c..14387eed2 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/oat_file.cc b/runtime/oat_file.cc index 6fda79069..55a2fbb00 100644 --- a/runtime/oat_file.cc +++ b/runtime/oat_file.cc @@ -21,6 +21,9 @@ #include #include +#ifndef __APPLE__ +#include // for dl_iterate_phdr. +#endif #include // 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 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,27 @@ 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(data); + if (info->dlpi_name != nullptr && info->dlpi_name == context->so_name) { + for (int i = 0; i < info->dlpi_phnum; i++) { + if (info->dlpi_phdr[i].p_type == PT_LOAD) { + auto vaddr = reinterpret_cast(info->dlpi_addr + info->dlpi_phdr[i].p_vaddr); + MemMap::MapDummy(info->dlpi_name, vaddr, info->dlpi_phdr[i].p_memsz); + } + } + } + return 0; + } + std::string so_name; + } context; + context.so_name = elf_filename; + dl_iterate_phdr(dl_iterate_context::callback, &context); + 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/test/137-cfi/run b/test/137-cfi/run new file mode 100755 index 000000000..78cf2aaf8 --- /dev/null +++ b/test/137-cfi/run @@ -0,0 +1,21 @@ +#!/bin/bash +# +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Temporarily disable address space layout randomization (ASLR). +# This is need on host so that the linker loads core.oat at fixed address. +export LD_USE_LOAD_BIAS=1 + +exec ${RUN} "$@" diff --git a/test/137-cfi/src/Main.java b/test/137-cfi/src/Main.java index 658ba5309..a88adc1bc 100644 --- a/test/137-cfi/src/Main.java +++ b/test/137-cfi/src/Main.java @@ -26,7 +26,7 @@ import java.util.Comparator; public class Main implements Comparator
{ // Whether to test local unwinding. Libunwind uses linker info to find executables. As we do // not dlopen at the moment, this doesn't work, so keep it off for now. - public final static boolean TEST_LOCAL_UNWINDING = false; + public final static boolean TEST_LOCAL_UNWINDING = true; // Unwinding another process, modelling debuggerd. This doesn't use the linker, so should work // no matter whether we're using dlopen or not. -- 2.11.0