diff options
| -rw-r--r-- | runtime/mem_map.cc | 8 | ||||
| -rw-r--r-- | runtime/mem_map.h | 6 | ||||
| -rw-r--r-- | runtime/oat_file.cc | 39 | ||||
| -rwxr-xr-x | test/137-cfi/run | 21 | ||||
| -rw-r--r-- | test/137-cfi/src/Main.java | 2 |
5 files changed, 72 insertions, 4 deletions
diff --git a/runtime/mem_map.cc b/runtime/mem_map.cc index 2e335dcae5..7e640c65f1 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, reuse); } +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 6023a703c5..14387eed28 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 6fda790697..55a2fbb00d 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,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<dl_iterate_context*>(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<uint8_t*>(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 0000000000..78cf2aaf8d --- /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 658ba53099..a88adc1bcf 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<Main> { // 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. |