mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-22 16:37:31 +09:00
Issue #1053 - Remove android support from mozglue
Yes, I checked for unsaved files this time...
This commit is contained in:
parent
bb8b180863
commit
a890ecd06f
26 changed files with 19 additions and 2748 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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++;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue