mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1077384 - Make libmozglue a pseudo-LD_PRELOAD on android. r=nfroyd
In order to avoid adding more dlsym overhead than there already is, resolve symbols directly in the library containing the linker. (GetSymbolPtr is essentially free ; dlsym makes the system linker compule a ElfHash itself, and that's quite expensive to do on all symbols) This also paves the way for direct symbol resolution in all system libraries.
This commit is contained in:
parent
31a9d027d6
commit
c1730d5281
55
mozglue/linker/BaseElf.cpp
Normal file
55
mozglue/linker/BaseElf.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#include "BaseElf.h"
|
||||||
|
#include "Elfxx.h"
|
||||||
|
#include "Logging.h"
|
||||||
|
|
||||||
|
using namespace Elf;
|
||||||
|
|
||||||
|
unsigned long
|
||||||
|
BaseElf::Hash(const char *symbol)
|
||||||
|
{
|
||||||
|
const unsigned char *sym = reinterpret_cast<const unsigned char *>(symbol);
|
||||||
|
unsigned long h = 0, g;
|
||||||
|
while (*sym) {
|
||||||
|
h = (h << 4) + *sym++;
|
||||||
|
g = h & 0xf0000000;
|
||||||
|
h ^= g;
|
||||||
|
h ^= g >> 24;
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *
|
||||||
|
BaseElf::GetSymbolPtr(const char *symbol, unsigned long hash) const
|
||||||
|
{
|
||||||
|
const Sym *sym = GetSymbol(symbol, hash);
|
||||||
|
void *ptr = nullptr;
|
||||||
|
if (sym && sym->st_shndx != SHN_UNDEF)
|
||||||
|
ptr = GetPtr(sym->st_value);
|
||||||
|
DEBUG_LOG("BaseElf::GetSymbolPtr(%p [\"%s\"], \"%s\") = %p",
|
||||||
|
reinterpret_cast<const void *>(this), GetPath(), symbol, ptr);
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Sym *
|
||||||
|
BaseElf::GetSymbol(const char *symbol, unsigned long hash) const
|
||||||
|
{
|
||||||
|
/* Search symbol with the buckets and chains tables.
|
||||||
|
* The hash computed from the symbol name gives an index in the buckets
|
||||||
|
* table. The corresponding value in the bucket table is an index in the
|
||||||
|
* symbols table and in the chains table.
|
||||||
|
* If the corresponding symbol in the symbols table matches, we're done.
|
||||||
|
* Otherwise, the corresponding value in the chains table is a new index
|
||||||
|
* in both tables, which corresponding symbol is tested and so on and so
|
||||||
|
* forth */
|
||||||
|
size_t bucket = hash % buckets.numElements();
|
||||||
|
for (size_t y = buckets[bucket]; y != STN_UNDEF; y = chains[y]) {
|
||||||
|
if (strcmp(symbol, strtab.GetStringAt(symtab[y].st_name)))
|
||||||
|
continue;
|
||||||
|
return &symtab[y];
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
93
mozglue/linker/BaseElf.h
Normal file
93
mozglue/linker/BaseElf.h
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
#ifndef BaseElf_h
|
||||||
|
#define BaseElf_h
|
||||||
|
|
||||||
|
#include "ElfLoader.h"
|
||||||
|
#include "Elfxx.h"
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for ELF libraries. This class includes things that will be
|
||||||
|
* common between SystemElfs and CustomElfs.
|
||||||
|
*/
|
||||||
|
class BaseElf: public LibHandle
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Hash function for symbol lookup, as defined in ELF standard for System V.
|
||||||
|
*/
|
||||||
|
static unsigned long Hash(const char *symbol);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the address corresponding to the given symbol name (with a
|
||||||
|
* pre-computed hash).
|
||||||
|
*/
|
||||||
|
void *GetSymbolPtr(const char *symbol, unsigned long hash) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a pointer to the Elf Symbol in the Dynamic Symbol table
|
||||||
|
* corresponding to the given symbol name (with a pre-computed hash).
|
||||||
|
*/
|
||||||
|
const Elf::Sym *GetSymbol(const char *symbol, unsigned long hash) const;
|
||||||
|
|
||||||
|
BaseElf(const char *path)
|
||||||
|
: LibHandle(path) { }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
* Inherited from LibHandle. Those are temporary and are not supposed to
|
||||||
|
* be used.
|
||||||
|
*/
|
||||||
|
virtual void *GetSymbolPtr(const char *symbol) const { return NULL; };
|
||||||
|
virtual bool Contains(void *addr) const { return false; };
|
||||||
|
virtual void *GetBase() const { return GetPtr(0); }
|
||||||
|
|
||||||
|
#ifdef __ARM_EABI__
|
||||||
|
virtual const void *FindExidx(int *pcount) const { return NULL; };
|
||||||
|
#endif
|
||||||
|
|
||||||
|
virtual Mappable *GetMappable() const { return NULL; };
|
||||||
|
|
||||||
|
public:
|
||||||
|
/* private: */
|
||||||
|
/**
|
||||||
|
* Returns a pointer relative to the base address where the library is
|
||||||
|
* loaded.
|
||||||
|
*/
|
||||||
|
void *GetPtr(const Elf::Addr offset) const
|
||||||
|
{
|
||||||
|
if (reinterpret_cast<void *>(offset) > base)
|
||||||
|
return reinterpret_cast<void *>(offset);
|
||||||
|
return base + offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Like the above, but returns a typed (const) pointer
|
||||||
|
*/
|
||||||
|
template <typename T>
|
||||||
|
const T *GetPtr(const Elf::Addr offset) const
|
||||||
|
{
|
||||||
|
if (reinterpret_cast<void *>(offset) > base)
|
||||||
|
return reinterpret_cast<const T *>(offset);
|
||||||
|
return reinterpret_cast<const T *>(base + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Base address where the library is loaded */
|
||||||
|
MappedPtr base;
|
||||||
|
|
||||||
|
/* Buckets and chains for the System V symbol hash table */
|
||||||
|
Array<Elf::Word> buckets;
|
||||||
|
UnsizedArray<Elf::Word> chains;
|
||||||
|
|
||||||
|
/* protected: */
|
||||||
|
/* String table */
|
||||||
|
Elf::Strtab strtab;
|
||||||
|
|
||||||
|
/* Symbol table */
|
||||||
|
UnsizedArray<Elf::Sym> symtab;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* BaseElf_h */
|
@ -7,7 +7,9 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <string.h>
|
||||||
#include "CustomElf.h"
|
#include "CustomElf.h"
|
||||||
|
#include "BaseElf.h"
|
||||||
#include "Mappable.h"
|
#include "Mappable.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
|
|
||||||
@ -279,43 +281,10 @@ CustomElf::~CustomElf()
|
|||||||
ElfLoader::Singleton.Forget(this);
|
ElfLoader::Singleton.Forget(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hash function for symbol lookup, as defined in ELF standard for System V
|
|
||||||
*/
|
|
||||||
unsigned long
|
|
||||||
ElfHash(const char *symbol)
|
|
||||||
{
|
|
||||||
const unsigned char *sym = reinterpret_cast<const unsigned char *>(symbol);
|
|
||||||
unsigned long h = 0, g;
|
|
||||||
while (*sym) {
|
|
||||||
h = (h << 4) + *sym++;
|
|
||||||
if ((g = h & 0xf0000000))
|
|
||||||
h ^= g >> 24;
|
|
||||||
h &= ~g;
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* anonymous namespace */
|
|
||||||
|
|
||||||
void *
|
void *
|
||||||
CustomElf::GetSymbolPtr(const char *symbol) const
|
CustomElf::GetSymbolPtr(const char *symbol) const
|
||||||
{
|
{
|
||||||
return GetSymbolPtr(symbol, ElfHash(symbol));
|
return BaseElf::GetSymbolPtr(symbol, Hash(symbol));
|
||||||
}
|
|
||||||
|
|
||||||
void *
|
|
||||||
CustomElf::GetSymbolPtr(const char *symbol, unsigned long hash) const
|
|
||||||
{
|
|
||||||
const Sym *sym = GetSymbol(symbol, hash);
|
|
||||||
void *ptr = nullptr;
|
|
||||||
if (sym && sym->st_shndx != SHN_UNDEF)
|
|
||||||
ptr = GetPtr(sym->st_value);
|
|
||||||
DEBUG_LOG("CustomElf::GetSymbolPtr(%p [\"%s\"], \"%s\") = %p",
|
|
||||||
reinterpret_cast<const void *>(this), GetPath(), symbol, ptr);
|
|
||||||
return ptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *
|
void *
|
||||||
@ -372,16 +341,17 @@ CustomElf::GetSymbolPtrInDeps(const char *symbol) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *sym;
|
void *sym;
|
||||||
/* Search the symbol in the main program. Note this also tries all libraries
|
|
||||||
* the system linker will have loaded RTLD_GLOBAL. Unfortunately, that doesn't
|
unsigned long hash = Hash(symbol);
|
||||||
* work with bionic, but its linker doesn't normally search the main binary
|
|
||||||
* anyways. Moreover, on android, the main binary is dalvik. */
|
/* self_elf should never be NULL, but better safe than sorry. */
|
||||||
#ifdef __GLIBC__
|
if (ElfLoader::Singleton.self_elf) {
|
||||||
sym = dlsym(RTLD_DEFAULT, symbol);
|
/* We consider the library containing this code a permanent LD_PRELOAD,
|
||||||
DEBUG_LOG("dlsym(RTLD_DEFAULT, \"%s\") = %p", symbol, sym);
|
* so, check if the symbol exists here first. */
|
||||||
if (sym)
|
sym = ElfLoader::Singleton.self_elf->GetSymbolPtr(symbol, hash);
|
||||||
return sym;
|
if (sym)
|
||||||
#endif
|
return sym;
|
||||||
|
}
|
||||||
|
|
||||||
/* Then search the symbol in our dependencies. Since we already searched in
|
/* Then search the symbol in our dependencies. Since we already searched in
|
||||||
* libraries the system linker loaded, skip those (on glibc systems). We
|
* libraries the system linker loaded, skip those (on glibc systems). We
|
||||||
@ -389,15 +359,13 @@ CustomElf::GetSymbolPtrInDeps(const char *symbol) const
|
|||||||
* directly, not in their own dependent libraries. Building libraries with
|
* directly, not in their own dependent libraries. Building libraries with
|
||||||
* --no-allow-shlib-undefined ensures such indirect symbol dependency don't
|
* --no-allow-shlib-undefined ensures such indirect symbol dependency don't
|
||||||
* happen. */
|
* happen. */
|
||||||
unsigned long hash = ElfHash(symbol);
|
|
||||||
for (std::vector<RefPtr<LibHandle> >::const_iterator it = dependencies.begin();
|
for (std::vector<RefPtr<LibHandle> >::const_iterator it = dependencies.begin();
|
||||||
it < dependencies.end(); ++it) {
|
it < dependencies.end(); ++it) {
|
||||||
if (!(*it)->IsSystemElf()) {
|
if (!(*it)->IsSystemElf()) {
|
||||||
sym = reinterpret_cast<CustomElf *>((*it).get())->GetSymbolPtr(symbol, hash);
|
sym = static_cast<BaseElf *>(
|
||||||
#ifndef __GLIBC__
|
static_cast<CustomElf *>((*it).get()))->GetSymbolPtr(symbol, hash);
|
||||||
} else {
|
} else {
|
||||||
sym = (*it)->GetSymbolPtr(symbol);
|
sym = (*it)->GetSymbolPtr(symbol);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
if (sym)
|
if (sym)
|
||||||
return sym;
|
return sym;
|
||||||
@ -405,26 +373,6 @@ CustomElf::GetSymbolPtrInDeps(const char *symbol) const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Sym *
|
|
||||||
CustomElf::GetSymbol(const char *symbol, unsigned long hash) const
|
|
||||||
{
|
|
||||||
/* Search symbol with the buckets and chains tables.
|
|
||||||
* The hash computed from the symbol name gives an index in the buckets
|
|
||||||
* table. The corresponding value in the bucket table is an index in the
|
|
||||||
* symbols table and in the chains table.
|
|
||||||
* If the corresponding symbol in the symbols table matches, we're done.
|
|
||||||
* Otherwise, the corresponding value in the chains table is a new index
|
|
||||||
* in both tables, which corresponding symbol is tested and so on and so
|
|
||||||
* forth */
|
|
||||||
size_t bucket = hash % buckets.numElements();
|
|
||||||
for (size_t y = buckets[bucket]; y != STN_UNDEF; y = chains[y]) {
|
|
||||||
if (strcmp(symbol, strtab.GetStringAt(symtab[y].st_name)))
|
|
||||||
continue;
|
|
||||||
return &symtab[y];
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CustomElf::Contains(void *addr) const
|
CustomElf::Contains(void *addr) const
|
||||||
{
|
{
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#define CustomElf_h
|
#define CustomElf_h
|
||||||
|
|
||||||
#include "ElfLoader.h"
|
#include "ElfLoader.h"
|
||||||
|
#include "BaseElf.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
#include "Elfxx.h"
|
#include "Elfxx.h"
|
||||||
|
|
||||||
@ -13,7 +14,7 @@
|
|||||||
* Library Handle class for ELF libraries we don't let the system linker
|
* Library Handle class for ELF libraries we don't let the system linker
|
||||||
* handle.
|
* handle.
|
||||||
*/
|
*/
|
||||||
class CustomElf: public LibHandle, private ElfLoader::link_map
|
class CustomElf: public BaseElf, private ElfLoader::link_map
|
||||||
{
|
{
|
||||||
friend class ElfLoader;
|
friend class ElfLoader;
|
||||||
friend class SEGVHandler;
|
friend class SEGVHandler;
|
||||||
@ -31,7 +32,7 @@ public:
|
|||||||
const char *path, int flags);
|
const char *path, int flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Inherited from LibHandle
|
* Inherited from LibHandle/BaseElf
|
||||||
*/
|
*/
|
||||||
virtual ~CustomElf();
|
virtual ~CustomElf();
|
||||||
virtual void *GetSymbolPtr(const char *symbol) const;
|
virtual void *GetSymbolPtr(const char *symbol) const;
|
||||||
@ -54,18 +55,6 @@ public:
|
|||||||
void stats(const char *when) const;
|
void stats(const char *when) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
|
||||||
* Returns a pointer to the Elf Symbol in the Dynamic Symbol table
|
|
||||||
* corresponding to the given symbol name (with a pre-computed hash).
|
|
||||||
*/
|
|
||||||
const Elf::Sym *GetSymbol(const char *symbol, unsigned long hash) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the address corresponding to the given symbol name (with a
|
|
||||||
* pre-computed hash).
|
|
||||||
*/
|
|
||||||
void *GetSymbolPtr(const char *symbol, unsigned long hash) const;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Scan dependent libraries to find the address corresponding to the
|
* Scan dependent libraries to find the address corresponding to the
|
||||||
* given symbol name. This is used to find symbols that are undefined
|
* given symbol name. This is used to find symbols that are undefined
|
||||||
@ -77,7 +66,7 @@ private:
|
|||||||
* Private constructor
|
* Private constructor
|
||||||
*/
|
*/
|
||||||
CustomElf(Mappable *mappable, const char *path)
|
CustomElf(Mappable *mappable, const char *path)
|
||||||
: LibHandle(path)
|
: BaseElf(path)
|
||||||
, mappable(mappable)
|
, mappable(mappable)
|
||||||
, init(0)
|
, init(0)
|
||||||
, fini(0)
|
, fini(0)
|
||||||
@ -85,24 +74,6 @@ private:
|
|||||||
, has_text_relocs(false)
|
, has_text_relocs(false)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a pointer relative to the base address where the library is
|
|
||||||
* loaded.
|
|
||||||
*/
|
|
||||||
void *GetPtr(const Elf::Addr offset) const
|
|
||||||
{
|
|
||||||
return base + offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Like the above, but returns a typed (const) pointer
|
|
||||||
*/
|
|
||||||
template <typename T>
|
|
||||||
const T *GetPtr(const Elf::Addr offset) const
|
|
||||||
{
|
|
||||||
return reinterpret_cast<const T *>(base + offset);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads an Elf segment defined by the given PT_LOAD header.
|
* Loads an Elf segment defined by the given PT_LOAD header.
|
||||||
* Returns whether this succeeded or failed.
|
* Returns whether this succeeded or failed.
|
||||||
@ -167,19 +138,6 @@ private:
|
|||||||
/* Appropriated Mappable */
|
/* Appropriated Mappable */
|
||||||
mozilla::RefPtr<Mappable> mappable;
|
mozilla::RefPtr<Mappable> mappable;
|
||||||
|
|
||||||
/* Base address where the library is loaded */
|
|
||||||
MappedPtr base;
|
|
||||||
|
|
||||||
/* String table */
|
|
||||||
Elf::Strtab strtab;
|
|
||||||
|
|
||||||
/* Symbol table */
|
|
||||||
UnsizedArray<Elf::Sym> symtab;
|
|
||||||
|
|
||||||
/* Buckets and chains for the System V symbol hash table */
|
|
||||||
Array<Elf::Word> buckets;
|
|
||||||
UnsizedArray<Elf::Word> chains;
|
|
||||||
|
|
||||||
/* List of dependent libraries */
|
/* List of dependent libraries */
|
||||||
std::vector<mozilla::RefPtr<LibHandle> > dependencies;
|
std::vector<mozilla::RefPtr<LibHandle> > dependencies;
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "ElfLoader.h"
|
#include "ElfLoader.h"
|
||||||
|
#include "BaseElf.h"
|
||||||
#include "CustomElf.h"
|
#include "CustomElf.h"
|
||||||
#include "Mappable.h"
|
#include "Mappable.h"
|
||||||
#include "Logging.h"
|
#include "Logging.h"
|
||||||
@ -38,6 +39,10 @@ extern "C" MOZ_EXPORT const void *
|
|||||||
__gnu_Unwind_Find_exidx(void *pc, int *pcount) __attribute__((weak));
|
__gnu_Unwind_Find_exidx(void *pc, int *pcount) __attribute__((weak));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Pointer to the PT_DYNAMIC section of the executable or library
|
||||||
|
* containing this code. */
|
||||||
|
extern "C" Elf::Dyn _DYNAMIC[];
|
||||||
|
|
||||||
using namespace mozilla;
|
using namespace mozilla;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -331,6 +336,10 @@ ElfLoader::Load(const char *path, int flags, LibHandle *parent)
|
|||||||
/* Ensure logging is initialized or refresh if environment changed. */
|
/* Ensure logging is initialized or refresh if environment changed. */
|
||||||
Logging::Init();
|
Logging::Init();
|
||||||
|
|
||||||
|
/* Ensure self_elf initialization. */
|
||||||
|
if (!self_elf)
|
||||||
|
Init();
|
||||||
|
|
||||||
RefPtr<LibHandle> handle;
|
RefPtr<LibHandle> handle;
|
||||||
|
|
||||||
/* Handle dlopen(nullptr) directly. */
|
/* Handle dlopen(nullptr) directly. */
|
||||||
@ -466,6 +475,54 @@ ElfLoader::Forget(LibHandle *handle)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
/* Ideally, we wouldn't be initializing self_elf this way, but until
|
||||||
|
* SystemElf actually inherits from BaseElf, we'll just do it this
|
||||||
|
* (gross) way. */
|
||||||
|
UniquePtr<BaseElf> elf = mozilla::MakeUnique<BaseElf>(info.dli_fname);
|
||||||
|
elf->base.Assign(info.dli_fbase, -1);
|
||||||
|
size_t symnum = 0;
|
||||||
|
for (const Elf::Dyn *dyn = _DYNAMIC; dyn->d_tag; dyn++) {
|
||||||
|
switch (dyn->d_tag) {
|
||||||
|
case DT_HASH:
|
||||||
|
{
|
||||||
|
DEBUG_LOG("%s 0x%08" PRIxAddr, "DT_HASH", dyn->d_un.d_val);
|
||||||
|
const Elf::Word *hash_table_header = \
|
||||||
|
elf->GetPtr<Elf::Word>(dyn->d_un.d_ptr);
|
||||||
|
symnum = hash_table_header[1];
|
||||||
|
elf->buckets.Init(&hash_table_header[2], hash_table_header[0]);
|
||||||
|
elf->chains.Init(&*elf->buckets.end());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DT_STRTAB:
|
||||||
|
DEBUG_LOG("%s 0x%08" PRIxAddr, "DT_STRTAB", dyn->d_un.d_val);
|
||||||
|
elf->strtab.Init(elf->GetPtr(dyn->d_un.d_ptr));
|
||||||
|
break;
|
||||||
|
case DT_SYMTAB:
|
||||||
|
DEBUG_LOG("%s 0x%08" PRIxAddr, "DT_SYMTAB", dyn->d_un.d_val);
|
||||||
|
elf->symtab.Init(elf->GetPtr(dyn->d_un.d_ptr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!elf->buckets || !symnum) {
|
||||||
|
ERROR("%s: Missing or broken DT_HASH", info.dli_fname);
|
||||||
|
} else if (!elf->strtab) {
|
||||||
|
ERROR("%s: Missing DT_STRTAB", info.dli_fname);
|
||||||
|
} else if (!elf->symtab) {
|
||||||
|
ERROR("%s: Missing DT_SYMTAB", info.dli_fname);
|
||||||
|
} else {
|
||||||
|
self_elf = Move(elf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ElfLoader::~ElfLoader()
|
ElfLoader::~ElfLoader()
|
||||||
{
|
{
|
||||||
LibHandleList list;
|
LibHandleList list;
|
||||||
@ -507,6 +564,10 @@ ElfLoader::~ElfLoader()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Avoid self_elf->base destructor unmapping something that doesn't actually
|
||||||
|
* belong to it. */
|
||||||
|
if (self_elf)
|
||||||
|
self_elf->base.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
|
#include "mozilla/UniquePtr.h"
|
||||||
#include "Zip.h"
|
#include "Zip.h"
|
||||||
#include "Elfxx.h"
|
#include "Elfxx.h"
|
||||||
#include "Mappable.h"
|
#include "Mappable.h"
|
||||||
@ -63,6 +64,9 @@ IsSignalHandlingBroken();
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Forward declaration because BaseElf.h includes ElfLoader.h */
|
||||||
|
class BaseElf;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specialize RefCounted template for LibHandle. We may get references to
|
* Specialize RefCounted template for LibHandle. We may get references to
|
||||||
* LibHandles during the execution of their destructor, so we need
|
* LibHandles during the execution of their destructor, so we need
|
||||||
@ -439,6 +443,13 @@ protected:
|
|||||||
private:
|
private:
|
||||||
~ElfLoader();
|
~ElfLoader();
|
||||||
|
|
||||||
|
/* Initialization code that can't run during static initialization. */
|
||||||
|
void Init();
|
||||||
|
|
||||||
|
/* System loader handle for the library/program containing our code. This
|
||||||
|
* is used to resolve wrapped functions. */
|
||||||
|
mozilla::UniquePtr<BaseElf> self_elf;
|
||||||
|
|
||||||
/* Bookkeeping */
|
/* Bookkeeping */
|
||||||
typedef std::vector<LibHandle *> LibHandleList;
|
typedef std::vector<LibHandle *> LibHandleList;
|
||||||
LibHandleList handles;
|
LibHandleList handles;
|
||||||
@ -557,6 +568,12 @@ private:
|
|||||||
} r_state;
|
} r_state;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Memory representation of ELF Auxiliary Vectors */
|
||||||
|
struct AuxVector {
|
||||||
|
Elf::Addr type;
|
||||||
|
Elf::Addr value;
|
||||||
|
};
|
||||||
|
|
||||||
/* Helper class used to integrate libraries loaded by this linker in
|
/* Helper class used to integrate libraries loaded by this linker in
|
||||||
* r_debug */
|
* r_debug */
|
||||||
class DebuggerHelper
|
class DebuggerHelper
|
||||||
@ -564,6 +581,8 @@ private:
|
|||||||
public:
|
public:
|
||||||
DebuggerHelper();
|
DebuggerHelper();
|
||||||
|
|
||||||
|
void Init(AuxVector *auvx);
|
||||||
|
|
||||||
operator bool()
|
operator bool()
|
||||||
{
|
{
|
||||||
return dbg;
|
return dbg;
|
||||||
|
@ -290,6 +290,10 @@ public:
|
|||||||
static_cast<T *>(this)->munmap(get(), GetLength());
|
static_cast<T *>(this)->munmap(get(), GetLength());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void release()
|
||||||
|
{
|
||||||
|
MemoryRange::Assign(MAP_FAILED, 0);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MappedPtr: public GenericMappedPtr<MappedPtr>
|
struct MappedPtr: public GenericMappedPtr<MappedPtr>
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
|
'BaseElf.cpp',
|
||||||
'CustomElf.cpp',
|
'CustomElf.cpp',
|
||||||
'ElfLoader.cpp',
|
'ElfLoader.cpp',
|
||||||
'Mappable.cpp',
|
'Mappable.cpp',
|
||||||
|
Loading…
Reference in New Issue
Block a user