Bug 1898382 - Remove Android < 5.0 specific code from the linker. r=gsvelto

Also remove workarounds for older NDKs.

Differential Revision: https://phabricator.services.mozilla.com/D211299
This commit is contained in:
Mike Hommey 2024-05-23 06:48:36 +00:00
parent 67a6fa45ec
commit 3adb098477
3 changed files with 31 additions and 153 deletions

View file

@ -7,6 +7,7 @@
#include <cstdlib> #include <cstdlib>
#include <cstdio> #include <cstdio>
#include <dlfcn.h> #include <dlfcn.h>
#include <link.h>
#include <optional> #include <optional>
#include <unistd.h> #include <unistd.h>
#include <errno.h> #include <errno.h>
@ -55,12 +56,6 @@ extern "C" MOZ_EXPORT const void* __gnu_Unwind_Find_exidx(void* pc, int* pcount)
__attribute__((weak)); __attribute__((weak));
#endif #endif
/* Ideally we'd #include <link.h>, but that's a world of pain
* Moreover, not all versions of android support it, so we need a weak
* reference. */
extern "C" MOZ_EXPORT int dl_iterate_phdr(dl_phdr_cb callback, void* data)
__attribute__((weak));
/* Pointer to the PT_DYNAMIC section of the executable or library /* Pointer to the PT_DYNAMIC section of the executable or library
* containing this code. */ * containing this code. */
extern "C" Elf::Dyn _DYNAMIC[]; extern "C" Elf::Dyn _DYNAMIC[];
@ -246,33 +241,18 @@ int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void* data) {
DlIteratePhdrHelper helper; DlIteratePhdrHelper helper;
AutoLock lock(&ElfLoader::Singleton.handlesMutex); AutoLock lock(&ElfLoader::Singleton.handlesMutex);
if (dl_iterate_phdr) { for (ElfLoader::LibHandleList::reverse_iterator it =
for (ElfLoader::LibHandleList::reverse_iterator it = ElfLoader::Singleton.handles.rbegin();
ElfLoader::Singleton.handles.rbegin(); it < ElfLoader::Singleton.handles.rend(); ++it) {
it < ElfLoader::Singleton.handles.rend(); ++it) { BaseElf* elf = (*it)->AsBaseElf();
BaseElf* elf = (*it)->AsBaseElf(); if (!elf) {
if (!elf) { continue;
continue;
}
int ret = helper.fill_and_call(callback, (*it)->GetBase(),
(*it)->GetPath(), data);
if (ret) return ret;
} }
return dl_iterate_phdr(callback, data); int ret = helper.fill_and_call(callback, (*it)->GetBase(), (*it)->GetPath(),
} data);
/* For versions of Android that don't support dl_iterate_phdr (< 5.0),
* we go through the debugger helper data, which is known to be racy, but
* there's not much we can do about this :( . */
if (!ElfLoader::Singleton.dbg) return -1;
for (ElfLoader::DebuggerHelper::iterator it =
ElfLoader::Singleton.dbg.begin();
it < ElfLoader::Singleton.dbg.end(); ++it) {
int ret = helper.fill_and_call(callback, it->l_addr, it->l_name, data);
if (ret) return ret; if (ret) return ret;
} }
return 0; return dl_iterate_phdr(callback, data);
} }
#ifdef __ARM_EABI__ #ifdef __ARM_EABI__
@ -304,11 +284,6 @@ const char* LeafName(const char* path) {
*/ */
template <class Lambda> template <class Lambda>
static bool RunWithSystemLinkerLock(Lambda&& aLambda) { static bool RunWithSystemLinkerLock(Lambda&& aLambda) {
if (!dl_iterate_phdr) {
// No dl_iterate_phdr support.
return false;
}
#if defined(ANDROID) #if defined(ANDROID)
if (GetAndroidSDKVersion() < 23) { if (GetAndroidSDKVersion() < 23) {
// dl_iterate_phdr is _not_ protected by a lock on Android < 23. // dl_iterate_phdr is _not_ protected by a lock on Android < 23.
@ -530,19 +505,6 @@ void ElfLoader::Init() {
if (dladdr(_DYNAMIC, &info) != 0) { if (dladdr(_DYNAMIC, &info) != 0) {
self_elf = LoadedElf::Create(info.dli_fname, info.dli_fbase); self_elf = LoadedElf::Create(info.dli_fname, info.dli_fbase);
} }
#if defined(ANDROID)
// On Android < 5.0, resolving weak symbols via dlsym doesn't work.
// The weak symbols Gecko uses are in either libc or libm, so we
// wrap those such that this linker does symbol resolution for them.
if (GetAndroidSDKVersion() < 21) {
if (dladdr(FunctionPtr(syscall), &info) != 0) {
libc = LoadedElf::Create(info.dli_fname, info.dli_fbase);
}
if (dladdr(FunctionPtr<int (*)(double)>(isnan), &info) != 0) {
libm = LoadedElf::Create(info.dli_fname, info.dli_fbase);
}
}
#endif
} }
ElfLoader::~ElfLoader() { ElfLoader::~ElfLoader() {
@ -554,10 +516,6 @@ ElfLoader::~ElfLoader() {
/* Release self_elf and libc */ /* Release self_elf and libc */
self_elf = nullptr; self_elf = nullptr;
#if defined(ANDROID)
libc = nullptr;
libm = nullptr;
#endif
AutoLock lock(&handlesMutex); AutoLock lock(&handlesMutex);
/* Build up a list of all library handles with direct (external) references. /* Build up a list of all library handles with direct (external) references.
@ -701,8 +659,7 @@ ElfLoader::DebuggerHelper::DebuggerHelper()
/* Finally, scan forward to find the last environment variable pointer and /* Finally, scan forward to find the last environment variable pointer and
* thus the first auxiliary vector. */ * thus the first auxiliary vector. */
while (*scan++) while (*scan++);
;
/* Some platforms have more NULLs here, so skip them if we encounter them */ /* Some platforms have more NULLs here, so skip them if we encounter them */
while (!*scan) scan++; while (!*scan) scan++;

View file

@ -34,13 +34,6 @@ typedef struct {
#endif #endif
int __wrap_dladdr(const void* addr, Dl_info* info); int __wrap_dladdr(const void* addr, Dl_info* info);
struct dl_phdr_info {
Elf::Addr dlpi_addr;
const char* dlpi_name;
const Elf::Phdr* dlpi_phdr;
Elf::Half dlpi_phnum;
};
typedef int (*dl_phdr_cb)(struct dl_phdr_info*, size_t, void*); typedef int (*dl_phdr_cb)(struct dl_phdr_info*, size_t, void*);
int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void* data); int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void* data);
@ -408,17 +401,6 @@ class ElfLoader : public SEGVHandler {
* is used to resolve wrapped functions. */ * is used to resolve wrapped functions. */
RefPtr<LibHandle> self_elf; 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;
/* And for libm. */
RefPtr<LibHandle> libm;
#endif
/* Bookkeeping */ /* Bookkeeping */
typedef std::vector<LibHandle*> LibHandleList; typedef std::vector<LibHandle*> LibHandleList;
LibHandleList handles; LibHandleList handles;

View file

@ -7,21 +7,9 @@
#include "Utils.h" #include "Utils.h"
/** #include <elf.h>
* Android system headers have two different elf.h file. The one under linux/
* is the most complete on older Android API versions without unified headers.
*/
#if defined(ANDROID) && __ANDROID_API__ < 21 && !defined(__ANDROID_API_L__)
# include <linux/elf.h>
#else
# include <elf.h>
#endif
#include <endian.h> #include <endian.h>
#if defined(__ARM_EABI__) && !defined(PT_ARM_EXIDX)
# define PT_ARM_EXIDX 0x70000001
#endif
/** /**
* Generic ELF macros for the target system * Generic ELF macros for the target system
*/ */
@ -128,58 +116,6 @@
# error Unknown ELF machine type # error Unknown ELF machine type
#endif #endif
/**
* Android system headers don't have all definitions
*/
#ifndef STN_UNDEF
# define STN_UNDEF 0
#endif
#ifndef DT_INIT_ARRAY
# define DT_INIT_ARRAY 25
#endif
#ifndef DT_FINI_ARRAY
# define DT_FINI_ARRAY 26
#endif
#ifndef DT_INIT_ARRAYSZ
# define DT_INIT_ARRAYSZ 27
#endif
#ifndef DT_FINI_ARRAYSZ
# define DT_FINI_ARRAYSZ 28
#endif
#ifndef DT_RELACOUNT
# define DT_RELACOUNT 0x6ffffff9
#endif
#ifndef DT_RELCOUNT
# define DT_RELCOUNT 0x6ffffffa
#endif
#ifndef DT_VERSYM
# define DT_VERSYM 0x6ffffff0
#endif
#ifndef DT_VERDEF
# define DT_VERDEF 0x6ffffffc
#endif
#ifndef DT_VERDEFNUM
# define DT_VERDEFNUM 0x6ffffffd
#endif
#ifndef DT_VERNEED
# define DT_VERNEED 0x6ffffffe
#endif
#ifndef DT_VERNEEDNUM
# define DT_VERNEEDNUM 0x6fffffff
#endif
#ifndef DT_FLAGS_1
# define DT_FLAGS_1 0x6ffffffb
#endif
#ifndef DT_FLAGS
# define DT_FLAGS 30
#endif
#ifndef DF_SYMBOLIC
# define DF_SYMBOLIC 0x00000002
#endif
#ifndef DF_TEXTREL
# define DF_TEXTREL 0x00000004
#endif
namespace Elf { namespace Elf {
/** /**
@ -220,26 +156,29 @@ class Strtab : public UnsizedArray<const char> {
/** /**
* Helper class around Elf relocation. * Helper class around Elf relocation.
*/ */
struct Rel : public Elf_(Rel) { struct Rel
/** : public Elf_(Rel){/**
* Returns the addend for the relocation, which is the value stored * Returns the addend for the relocation, which is the
* at r_offset. * value stored at r_offset.
*/ */
Addr GetAddend(void* base) const { Addr GetAddend(void* base)
return *(reinterpret_cast<const Addr*>(reinterpret_cast<const char*>(base) + const {return *(reinterpret_cast<const Addr*>(
r_offset)); reinterpret_cast<const char*>(base) + r_offset));
} } // namespace Elf
}; }
;
/** /**
* Helper class around Elf relocation with addend. * Helper class around Elf relocation with addend.
*/ */
struct Rela : public Elf_(Rela) { struct Rela
/** : public Elf_(Rela){/**
* Returns the addend for the relocation. * Returns the addend for the relocation.
*/ */
Addr GetAddend(void* base) const { return r_addend; } Addr GetAddend(void* base) const {return r_addend;
}; }
}
;
} /* namespace Elf */ } /* namespace Elf */