diff options
Diffstat (limited to 'mozglue/linker')
-rw-r--r-- | mozglue/linker/CustomElf.cpp | 10 | ||||
-rw-r--r-- | mozglue/linker/ElfLoader.cpp | 164 | ||||
-rw-r--r-- | mozglue/linker/ElfLoader.h | 8 | ||||
-rw-r--r-- | mozglue/linker/Elfxx.h | 8 | ||||
-rw-r--r-- | mozglue/linker/Logging.h | 35 | ||||
-rw-r--r-- | mozglue/linker/Mappable.cpp | 95 |
6 files changed, 2 insertions, 318 deletions
diff --git a/mozglue/linker/CustomElf.cpp b/mozglue/linker/CustomElf.cpp index dbab0cf0d..98d94fa8f 100644 --- a/mozglue/linker/CustomElf.cpp +++ b/mozglue/linker/CustomElf.cpp @@ -20,15 +20,8 @@ using namespace mozilla; /* Function used to report library mappings from the custom linker to Gecko * crash reporter */ -#ifdef ANDROID -extern "C" { - void report_mapping(char *name, void *base, uint32_t len, uint32_t offset); - void delete_mapping(const char *name); -} -#else #define report_mapping(...) #define delete_mapping(...) -#endif const Ehdr *Ehdr::validate(const void *buf) { @@ -162,13 +155,10 @@ CustomElf::Load(Mappable *mappable, const char *path, int flags) break; case PT_GNU_STACK: debug_phdr("PT_GNU_STACK", phdr); -// Skip on Android until bug 706116 is fixed -#ifndef ANDROID if (phdr->p_flags & PF_X) { ERROR("%s: Executable stack is not supported", elf->GetPath()); return nullptr; } -#endif break; #ifdef __ARM_EABI__ case PT_ARM_EXIDX: diff --git a/mozglue/linker/ElfLoader.cpp b/mozglue/linker/ElfLoader.cpp index 76225d1e7..dd3d7daa8 100644 --- a/mozglue/linker/ElfLoader.cpp +++ b/mozglue/linker/ElfLoader.cpp @@ -18,23 +18,6 @@ #include "Logging.h" #include <inttypes.h> -#if defined(ANDROID) -#include <sys/syscall.h> - -#include <android/api-level.h> -#if __ANDROID_API__ < 8 -/* Android API < 8 doesn't provide sigaltstack */ - -extern "C" { - -inline int sigaltstack(const stack_t *ss, stack_t *oss) { - return syscall(__NR_sigaltstack, ss, oss); -} - -} /* extern "C" */ -#endif /* __ANDROID_API__ */ -#endif /* ANDROID */ - #ifdef __ARM_EABI__ extern "C" MOZ_EXPORT const void * __gnu_Unwind_Find_exidx(void *pc, int *pcount) __attribute__((weak)); @@ -348,16 +331,6 @@ SystemElf::GetMappable() const const char *path = GetPath(); if (!path) return nullptr; -#ifdef ANDROID - /* On Android, if we don't have the full path, try in /system/lib */ - const char *name = LeafName(path); - std::string systemPath; - if (name == path) { - systemPath = "/system/lib/"; - systemPath += path; - path = systemPath.c_str(); - } -#endif return MappableFile::Create(path); } @@ -550,17 +523,9 @@ void ElfLoader::Init() { Dl_info info; - /* On Android < 4.1 can't reenter dl* functions. So when the library - * containing this code is dlopen()ed, it can't call dladdr from a - * static initializer. */ if (dladdr(_DYNAMIC, &info) != 0) { self_elf = LoadedElf::Create(info.dli_fname, info.dli_fbase); } -#if defined(ANDROID) - if (dladdr(FunctionPtr(syscall), &info) != 0) { - libc = LoadedElf::Create(info.dli_fname, info.dli_fbase); - } -#endif } ElfLoader::~ElfLoader() @@ -573,9 +538,6 @@ ElfLoader::~ElfLoader() /* Release self_elf and libc */ self_elf = nullptr; -#if defined(ANDROID) - libc = nullptr; -#endif /* Build up a list of all library handles with direct (external) references. * We actually skip system library handles because we want to keep at least @@ -962,88 +924,6 @@ ElfLoader::DebuggerHelper::Remove(ElfLoader::link_map *map) dbg->r_brk(); } -#if defined(ANDROID) -/* As some system libraries may be calling signal() or sigaction() to - * set a SIGSEGV handler, effectively breaking MappableSeekableZStream, - * or worse, restore our SIGSEGV handler with wrong flags (which using - * signal() will do), we want to hook into the system's sigaction() to - * replace it with our own wrapper instead, so that our handler is never - * replaced. We used to only do that with libraries this linker loads, - * but it turns out at least one system library does call signal() and - * breaks us (libsc-a3xx.so on the Samsung Galaxy S4). - * As libc's signal (bsd_signal/sysv_signal, really) calls sigaction - * under the hood, instead of calling the signal system call directly, - * we only need to hook sigaction. This is true for both bionic and - * glibc. - */ - -/* libc's sigaction */ -extern "C" int -sigaction(int signum, const struct sigaction *act, - struct sigaction *oldact); - -/* Simple reimplementation of sigaction. This is roughly equivalent - * to the assembly that comes in bionic, but not quite equivalent to - * glibc's implementation, so we only use this on Android. */ -int -sys_sigaction(int signum, const struct sigaction *act, - struct sigaction *oldact) -{ - return syscall(__NR_sigaction, signum, act, oldact); -} - -/* Replace the first instructions of the given function with a jump - * to the given new function. */ -template <typename T> -static bool -Divert(T func, T new_func) -{ - void *ptr = FunctionPtr(func); - uintptr_t addr = reinterpret_cast<uintptr_t>(ptr); - -#if defined(__i386__) - // A 32-bit jump is a 5 bytes instruction. - EnsureWritable w(ptr, 5); - *reinterpret_cast<unsigned char *>(addr) = 0xe9; // jmp - *reinterpret_cast<intptr_t *>(addr + 1) = - reinterpret_cast<uintptr_t>(new_func) - addr - 5; // target displacement - return true; -#elif defined(__arm__) - const unsigned char trampoline[] = { - // .thumb - 0x46, 0x04, // nop - 0x78, 0x47, // bx pc - 0x46, 0x04, // nop - // .arm - 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc, #-4] - // .word <new_func> - }; - const unsigned char *start; - if (addr & 0x01) { - /* Function is thumb, the actual address of the code is without the - * least significant bit. */ - addr--; - /* The arm part of the trampoline needs to be 32-bit aligned */ - if (addr & 0x02) - start = trampoline; - else - start = trampoline + 2; - } else { - /* Function is arm, we only need the arm part of the trampoline */ - start = trampoline + 6; - } - - size_t len = sizeof(trampoline) - (start - trampoline); - EnsureWritable w(reinterpret_cast<void *>(addr), len + sizeof(void *)); - memcpy(reinterpret_cast<void *>(addr), start, len); - *reinterpret_cast<void **>(addr + len) = FunctionPtr(new_func); - cacheflush(addr, addr + len + sizeof(void *), 0); - return true; -#else - return false; -#endif -} -#else #define sys_sigaction sigaction template <typename T> static bool @@ -1051,7 +931,7 @@ Divert(T func, T new_func) { return false; } -#endif + namespace { @@ -1144,48 +1024,6 @@ SEGVHandler::FinishInitialization() sigaction_func libc_sigaction; -#if defined(ANDROID) - /* Android > 4.4 comes with a sigaction wrapper in a LD_PRELOADed library - * (libsigchain) for ART. That wrapper kind of does the same trick as we - * do, so we need extra care in handling it. - * - Divert the libc's sigaction, assuming the LD_PRELOADed library uses - * it under the hood (which is more or less true according to the source - * of that library, since it's doing a lookup in RTLD_NEXT) - * - With the LD_PRELOADed library in place, all calls to sigaction from - * from system libraries will go to the LD_PRELOADed library. - * - The LD_PRELOADed library calls to sigaction go to our __wrap_sigaction. - * - The calls to sigaction from libraries faulty.lib loads are sent to - * the LD_PRELOADed library. - * In practice, for signal handling, this means: - * - The signal handler registered to the kernel is ours. - * - Our handler redispatches to the LD_PRELOADed library's if there's a - * segfault we don't handle. - * - The LD_PRELOADed library redispatches according to whatever system - * library or faulty.lib-loaded library set with sigaction. - * - * When there is no sigaction wrapper in place: - * - Divert the libc's sigaction. - * - Calls to sigaction from system library and faulty.lib-loaded libraries - * all go to the libc's sigaction, which end up in our __wrap_sigaction. - * - The signal handler registered to the kernel is ours. - * - Our handler redispatches according to whatever system library or - * faulty.lib-loaded library set with sigaction. - */ - void *libc = dlopen("libc.so", RTLD_GLOBAL | RTLD_LAZY); - if (libc) { - /* - * Lollipop bionic only has a small trampoline in sigaction, with the real - * work happening in __sigaction. Divert there instead of sigaction if it exists. - * Bug 1154803 - */ - libc_sigaction = reinterpret_cast<sigaction_func>(dlsym(libc, "__sigaction")); - - if (!libc_sigaction) { - libc_sigaction = - reinterpret_cast<sigaction_func>(dlsym(libc, "sigaction")); - } - } else -#endif { libc_sigaction = sigaction; } diff --git a/mozglue/linker/ElfLoader.h b/mozglue/linker/ElfLoader.h index 0d26a011e..033805460 100644 --- a/mozglue/linker/ElfLoader.h +++ b/mozglue/linker/ElfLoader.h @@ -471,14 +471,6 @@ private: * is used to resolve wrapped functions. */ RefPtr<LibHandle> self_elf; -#if defined(ANDROID) - /* System loader handle for the libc. This is used to resolve weak symbols - * that some libcs contain that the Android linker won't dlsym(). Normally, - * we wouldn't treat non-Android differently, but glibc uses versioned - * symbols which this linker doesn't support. */ - RefPtr<LibHandle> libc; -#endif - /* Bookkeeping */ typedef std::vector<LibHandle *> LibHandleList; LibHandleList handles; diff --git a/mozglue/linker/Elfxx.h b/mozglue/linker/Elfxx.h index b21a89336..33aa14ca4 100644 --- a/mozglue/linker/Elfxx.h +++ b/mozglue/linker/Elfxx.h @@ -5,15 +5,7 @@ #ifndef Elfxx_h #define Elfxx_h -/** - * Android system headers have two different elf.h file. The one under linux/ - * is the most complete on older android API versions. - */ -#if defined(ANDROID) && __ANDROID_API__ < 21 -#include <linux/elf.h> -#else #include <elf.h> -#endif #include <endian.h> #if defined(__ARM_EABI__) && !defined(PT_ARM_EXIDX) diff --git a/mozglue/linker/Logging.h b/mozglue/linker/Logging.h index 046d918f4..ec0a2b32b 100644 --- a/mozglue/linker/Logging.h +++ b/mozglue/linker/Logging.h @@ -7,41 +7,6 @@ #include "mozilla/Likely.h" -#ifdef ANDROID -#include <android/log.h> -#define LOG(...) __android_log_print(ANDROID_LOG_INFO, "GeckoLinker", __VA_ARGS__) -#define WARN(...) __android_log_print(ANDROID_LOG_WARN, "GeckoLinker", __VA_ARGS__) -#define ERROR(...) __android_log_print(ANDROID_LOG_ERROR, "GeckoLinker", __VA_ARGS__) -#else -#include <cstdio> - -/* Expand to 1 or m depending on whether there is one argument or more - * given. */ -#define MOZ_ONE_OR_MORE_ARGS_IMPL2(_1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) \ - N -#define MOZ_ONE_OR_MORE_ARGS_IMPL(args) MOZ_ONE_OR_MORE_ARGS_IMPL2 args -#define MOZ_ONE_OR_MORE_ARGS(...) \ - MOZ_ONE_OR_MORE_ARGS_IMPL((__VA_ARGS__, m, m, m, m, m, m, m, m, 1, 0)) - -#define MOZ_MACRO_GLUE(a, b) a b -#define MOZ_CONCAT2(a, b) a ## b -#define MOZ_CONCAT1(a, b) MOZ_CONCAT2(a, b) -#define MOZ_CONCAT(a, b) MOZ_CONCAT1(a, b) - -/* Some magic to choose between LOG1 and LOGm depending on the number of - * arguments */ -#define MOZ_CHOOSE_LOG(...) \ - MOZ_MACRO_GLUE(MOZ_CONCAT(LOG, MOZ_ONE_OR_MORE_ARGS(__VA_ARGS__)), \ - (__VA_ARGS__)) - -#define LOG1(format) fprintf(stderr, format "\n") -#define LOGm(format, ...) fprintf(stderr, format "\n", __VA_ARGS__) -#define LOG(...) MOZ_CHOOSE_LOG(__VA_ARGS__) -#define WARN(...) MOZ_CHOOSE_LOG("Warning: " __VA_ARGS__) -#define ERROR(...) MOZ_CHOOSE_LOG("Error: " __VA_ARGS__) - -#endif - class Logging { public: diff --git a/mozglue/linker/Mappable.cpp b/mozglue/linker/Mappable.cpp index 47b883d2d..1243a9e6e 100644 --- a/mozglue/linker/Mappable.cpp +++ b/mozglue/linker/Mappable.cpp @@ -15,9 +15,6 @@ #include "mozilla/UniquePtr.h" -#ifdef ANDROID -#include <linux/ashmem.h> -#endif #include <sys/stat.h> #include <errno.h> #include "ElfLoader.h" @@ -263,7 +260,6 @@ MappableExtractFile::Create(const char *name, Zip *zip, Zip::Stream *stream) * _MappableBuffer is a buffer which content can be mapped at different * locations in the virtual address space. * On Linux, uses a (deleted) temporary file on a tmpfs for sharable content. - * On Android, uses ashmem. */ class _MappableBuffer: public MappedPtr { @@ -275,57 +271,7 @@ public: static _MappableBuffer *Create(const char *name, size_t length) { AutoCloseFD fd; -#ifdef ANDROID - /* On Android, initialize an ashmem region with the given length */ - fd = open("/" ASHMEM_NAME_DEF, O_RDWR, 0600); - if (fd == -1) - return nullptr; - char str[ASHMEM_NAME_LEN]; - strlcpy(str, name, sizeof(str)); - ioctl(fd, ASHMEM_SET_NAME, str); - if (ioctl(fd, ASHMEM_SET_SIZE, length)) - return nullptr; - /* The Gecko crash reporter is confused by adjacent memory mappings of - * the same file and chances are we're going to map from the same file - * descriptor right away. To avoid problems with the crash reporter, - * create an empty anonymous page before or after the ashmem mapping, - * depending on how mappings grow in the address space. - */ -#if defined(__arm__) - void *buf = ::mmap(nullptr, length + PAGE_SIZE, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, 0); - if (buf != MAP_FAILED) { - ::mmap(AlignedEndPtr(reinterpret_cast<char *>(buf) + length, PAGE_SIZE), - PAGE_SIZE, PROT_NONE, MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - DEBUG_LOG("Decompression buffer of size 0x%x in ashmem \"%s\", mapped @%p", - length, str, buf); - return new _MappableBuffer(fd.forget(), buf, length); - } -#elif defined(__i386__) - size_t anon_mapping_length = length + PAGE_SIZE; - void *buf = ::mmap(nullptr, anon_mapping_length, PROT_NONE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - if (buf != MAP_FAILED) { - char *first_page = reinterpret_cast<char *>(buf); - char *map_page = first_page + PAGE_SIZE; - - void *actual_buf = ::mmap(map_page, length, PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_SHARED, fd, 0); - if (actual_buf == MAP_FAILED) { - ::munmap(buf, anon_mapping_length); - DEBUG_LOG("Fixed allocation of decompression buffer at %p failed", map_page); - return nullptr; - } - - DEBUG_LOG("Decompression buffer of size 0x%x in ashmem \"%s\", mapped @%p", - length, str, actual_buf); - return new _MappableBuffer(fd.forget(), actual_buf, length); - } -#else -#error need to add a case for your CPU -#endif -#else /* On Linux, use /dev/shm as base directory for temporary files, assuming * it's on tmpfs */ /* TODO: check that /dev/shm is tmpfs */ @@ -344,37 +290,16 @@ public: length, path, buf); return new _MappableBuffer(fd.forget(), buf, length); } -#endif + return nullptr; } void *mmap(const void *addr, size_t length, int prot, int flags, off_t offset) { MOZ_ASSERT(fd != -1); -#ifdef ANDROID - /* Mapping ashmem MAP_PRIVATE is like mapping anonymous memory, even when - * there is content in the ashmem */ - if (flags & MAP_PRIVATE) { - flags &= ~MAP_PRIVATE; - flags |= MAP_SHARED; - } -#endif return ::mmap(const_cast<void *>(addr), length, prot, flags, fd, offset); } -#ifdef ANDROID - ~_MappableBuffer() { - /* Free the additional page we allocated. See _MappableBuffer::Create */ -#if defined(__arm__) - ::munmap(AlignedEndPtr(*this + GetLength(), PAGE_SIZE), PAGE_SIZE); -#elif defined(__i386__) - ::munmap(*this - PAGE_SIZE, GetLength() + PAGE_SIZE); -#else -#error need to add a case for your CPU -#endif - } -#endif - private: _MappableBuffer(int fd, void *buf, size_t length) : MappedPtr(buf, length), fd(fd) { } @@ -440,15 +365,6 @@ MappableDeflate::mmap(const void *addr, size_t length, int prot, int flags, off_ } } } -#if defined(ANDROID) && defined(__arm__) - if (prot & PROT_EXEC) { - /* We just extracted data that may be executed in the future. - * We thus need to ensure Instruction and Data cache coherency. */ - DEBUG_LOG("cacheflush(%p, %p)", *buffer + offset, *buffer + (offset + length)); - cacheflush(reinterpret_cast<uintptr_t>(*buffer + offset), - reinterpret_cast<uintptr_t>(*buffer + (offset + length)), 0); - } -#endif return MemoryRange(buffer->mmap(addr, length, prot, flags, offset), length); } @@ -611,15 +527,6 @@ MappableSeekableZStream::ensure(const void *addr) if (!zStream.DecompressChunk(*buffer + chunkStart, chunk, length)) return false; -#if defined(ANDROID) && defined(__arm__) - if (map->prot & PROT_EXEC) { - /* We just extracted data that may be executed in the future. - * We thus need to ensure Instruction and Data cache coherency. */ - DEBUG_LOG("cacheflush(%p, %p)", *buffer + chunkStart, *buffer + (chunkStart + length)); - cacheflush(reinterpret_cast<uintptr_t>(*buffer + chunkStart), - reinterpret_cast<uintptr_t>(*buffer + (chunkStart + length)), 0); - } -#endif /* Only count if we haven't already decompressed parts of the chunk */ if (chunkAvail[chunk] == 0) chunkAvailNum++; |